它是当前运行的脚本的最后一个“脚本”元素吗?

Is it the last `script` element the currently running script?

本文关键字:脚本 元素 最后一个 运行      更新时间:2023-09-26

是否可以安全地假设当脚本运行**时文档中的最后一个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元素。文档的其余部分还不应该被加载,对吧?

这不是绝对的保证。查看这个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为"early",而不是当前运行脚本的id为"second"。

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

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

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

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

另一种选择是在脚本执行时使用document.write编写额外的内容。但是,这不会替换脚本标签,而只是在其后面添加一些内容。

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

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的修复,所以谁在乎呢:)