它是当前正在运行的脚本的最后一个 `script` 元素吗?

IT技术 javascript html dom
2021-02-26 14:15:37

假设script脚本运行**时文档中的最后一个元素*是当前正在运行的脚本是否安全?

例如,我想创建一个脚本,该脚本可以放置在页面正文的任何​​位置并在同一位置显示一个元素。我正在做这样的事情:

function getCurrentScriptElement() {
    var scripts = document.getElementsByTagName('script');
    return scripts[scripts.length - 1];
}

var script = getCurrentScriptElement();
var view = document.createElement('span');

/* Put stuff in our view... */

script.parentNode.insertBefore(view, script);

假设脚本在文档正文中,这是否“安全”?getCurrentScriptElement函数会始终返回正在运行的脚本吗?如果没有,怎么办?

我希望在不将脚本绑定到特定 id 属性或类似属性的情况下执行此操作,我希望它只是位置性的。


我在这里创建了一个拉入这个脚本的例子一个答案表明,其他脚本可能会创建这样的示例会中断的条件。是否可以向此示例添加其他脚本来破坏它?


有人建议其他带有deferasync属性的脚本可能会破坏这一点。任何人都可以举例说明这样的脚本如何工作?

据我了解,这defer意味着首先加载 DOM,然后使用defer标签运行脚本defer出现在另一个脚本元素上属性将如何影响getCurrentScriptElement?

async,据我所知,这意味着开始获取该脚本并同时继续解析 DOM,不要等待...但是当它遇到我的脚本时,它仍然应该停止并等待,对吧?

我看不出任何一个人会如何影响它,谁能提供一个例子?


* 为了这个问题,我只对外部脚本感兴趣。

** 不是script整个文档的最后一个script元素,而是它运行时文档的最后一个元素。文档的其余部分不应加载,对吗?

3个回答

这不是绝对的保证。看看这个 JSFiddle:http : //jsfiddle.net/jAsek/

<!DOCTYPE html>
<title>Test case</title>
<div>
    <p>At the start</p>
    <script id="first">
        var scr1 = document.createElement("script");
        scr1.setAttribute("id", "early");
        document.body.appendChild(scr1);
    </script>
    <p>After the first script</p>
    <script id="second">
        function getCurrentScriptElement() {
            var scripts = document.getElementsByTagName('script');
            return scripts[scripts.length - 1];
        }

        alert(getCurrentScriptElement().id);
    </script>
    <p>At the end</p>
</div>

这里的警报报告了“早期”注入脚本的 ID,而不是当前正在运行的脚本“第二个”的 ID。

内部和外部脚本之间没有实际区别。

有趣的。绝对没有我想的那么简单
2021-04-27 14:15:37
啊,等等,我已经制定了规则......它只适用于外部脚本,所以src属性会在那里。我可以检查一下。不过还是丑。
2021-05-01 14:15:37
@GGG如何检查脚本节点的文本内容是否存在代码中的唯一字符串?如果它不存在,请检查上一个脚本块,依此类推。
2021-05-08 14:15:37
不错,没想到 我想知道它是否可以解决。如果其他东西触发了 JSONP 请求,肯定会发生。外部脚本是对另一个答案的评论的回应。
2021-05-16 14:15:37
或者,如果您对规则没意见,为什么不简单地要求脚本标签上有一个固定的、唯一的 id?
2021-05-16 14:15:37

我认为这根本不是一个安全的假设,因为浏览器执行 javascript 代码的方式完全不同,这取决于许多因素(例如,如果您在头部有其他脚本元素,如果它们是外部元素等)。

您应该只要求人们使用具有自定义 ID 或类的虚拟元素。这样,您还可以在一个页面上多次执行任何操作,而无需多次运行脚本。

这也是使用小部件时所做的,例如 Google 的 +1 按钮。

另一种方法是document.write在脚本执行时使用编写附加内容。然而,这不会替换脚本标签,而只是在它之后添加一些东西。

您能否更清楚地了解第一段的含义,或者提供一个示例?如果我提供一个有效的脚本示例,您能否通过添加另一个脚本来打破它?
2021-04-21 14:15:37
Jonathan Lonowski,嗯,也许我正在寻找的那种答案可能包括对这些问题的检查?
2021-04-22 14:15:37
不幸的是,我真的不能给你一个例子或更多的细节(我实际上想把它写成评论,但没有因为我的回答的第二部分)。仅从经验和之前的讨论来看,浏览器在加载和执行 JS 的时间和方式方面的行为非常不同。
2021-05-04 14:15:37
@GGG 示例包括<script defer><script async>,它们都会影响执行时间并可能导致getCurrentScriptElement()不准确。document.currentScript似乎是有意/提议的解决方案,但似乎还没有得到很好的支持。
2021-05-05 14:15:37
我对第二部分不感兴趣(没有冒犯)......我想我应该将其添加到问题中。
2021-05-17 14:15:37

如果您的目标是 IE,您可能希望使用当前 90% 的浏览器支持的 document.currentScript 并回退到 document.scripts[document.scripts.length-1]

function writeHere(element)
{
 var sc = document.currentScript || document.scripts[document.scripts.length-1] ;  
 sc.parentNode.insertBefore(element, sc);
 // or in jquery $(sc).before($(element));
}

注意:我没有进行document.scripts[document.scripts.length-1]彻底的测试,但在大多数情况下它应该可以工作(但不是在 Alohci 示例中)。
这是 IE 的修复程序,所以谁在乎:)