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

时间:2013-01-19 00:55:04

标签: javascript html dom

假设脚本运行时文档中的最后一个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属性或类似属性的情况下执行此操作,我希望它只是位置。


我创建了一个here的示例this script。一个答案表明,其他脚本可能会创建一个像这样的例子会破坏的情况。是否可以在此示例中添加其他脚本来破坏它?


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

据我了解,defer表示首先加载DOM,然后使用defer标记运行脚本。如果defer属性出现在另一个脚本元素上会如何影响getCurrentScriptElement的行为?

async,据我所知,意味着开始获取该脚本并同时保持解析DOM,不要等待......但当它命中我的脚本时还是应该停下来等一下吧?

我看不出其中任何一方会如何影响它,有人能提供一个例子吗?


*出于此问题的目的,我只对外部脚本感兴趣。

**不是整个文档中的最后一个script元素,而是运行时文档中的最后一个script元素。该文档的其余部分尚未加载,对吧?

3 个答案:

答案 0 :(得分:4)

这不是绝对的保证。看看这个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,而不是当前正在运行的脚本“second”的id。

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

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:0)

您可能要使用目前90%的浏览器支持的document.currentScript ,如果要定位IE,则回退到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的修复程序,所以谁在乎:)