我如何引用加载当前正在执行的脚本的脚本标签?

IT技术 javascript element parent
2021-01-09 02:33:20

如何引用加载当前正在运行的 javascript 的脚本元素?

这是情况。我有一个“主”脚本被加载到页面的高处,第一件事是在 HEAD 标签下。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" src="scripts.js"></script>

“scripts.js”中有一个脚本需要能够按需加载其他脚本。普通方法对我来说不太适用,因为我需要在不引用 HEAD 标记的情况下添加新脚本,因为 HEAD 元素还没有完成渲染:

document.getElementsByTagName('head')[0].appendChild(v);

我想要做的是引用加载当前脚本的脚本元素,这样我就可以将新的动态加载的脚本标签附加到 DOM 之后。

<script type="text/javascript" src="scripts.js"></script>
loaded by scripts.js--><script type="text/javascript" src="new_script1.js"></script>
loaded by scripts.js --><script type="text/javascript" src="new_script2.js"></script>
6个回答

如何获取当前脚本元素:

1.使用 document.currentScript

document.currentScript将返回<script>当前正在处理其脚本元素。

<script>
var me = document.currentScript;
</script>

好处

  • 简单明了。可靠的。
  • 不需要修改脚本标签
  • 适用于异步脚本 ( defer& async)
  • 适用于动态插入的脚本

问题

  • 不适用于旧版浏览器和 IE。
  • 不适用于module <script type="module">

2.通过id选择脚本

为脚本提供一个 id 属性将使您可以轻松地通过 id 从 using 中选择它document.getElementById()

<script id="myscript">
var me = document.getElementById('myscript');
</script>

好处

  • 简单明了。可靠的。
  • 几乎普遍支持
  • 适用于异步脚本 ( defer& async)
  • 适用于动态插入的脚本

问题

  • 需要向脚本标签添加自定义属性
  • id 在某些边缘情况下,属性可能会导致某些浏览器中的脚本出现奇怪的行为

3. 使用data-*属性选择脚本

为脚本提供一个data-*属性将使您可以轻松地从内部选择它。

<script data-name="myscript">
var me = document.querySelector('script[data-name="myscript"]');
</script>

与前一个选项相比,这几乎没有什么好处。

好处

  • 简单明了。
  • 适用于异步脚本 ( defer& async)
  • 适用于动态插入的脚本

问题

  • 需要向脚本标签添加自定义属性
  • HTML5,并且querySelector()不兼容所有浏览器
  • 不如使用id属性得到广泛支持
  • 会得到解决<script>id边缘情况。
  • 如果页面上的另一个元素具有相同的数据属性和值,则可能会感到困惑。

4.通过src选择脚本

您可以使用选择器按源选择脚本,而不是使用数据属性:

<script src="//example.com/embed.js"></script>

在 embed.js 中:

var me = document.querySelector('script[src="//example.com/embed.js"]');

好处

  • 可靠的
  • 适用于异步脚本 ( defer& async)
  • 适用于动态插入的脚本
  • 不需要自定义属性或 ID

问题

  • 难道不是对本地脚本工作
  • 在不同的环境下会导致问题,比如开发和生产
  • 静电和脆弱。更改脚本文件的位置将需要修改脚本
  • 不如使用id属性得到广泛支持
  • 如果两次加载相同的脚本会导致问题

5. 遍历所有脚本以找到您想要的脚本

我们还可以遍历每个脚本元素并单独检查每个元素以选择我们想要的:

<script>
var me = null;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
    if( isMe(scripts[i])){
      me = scripts[i];
    }
}
</script>

这让我们可以在不能querySelector()很好地支持属性的旧浏览器中使用之前的两种技术例如:

function isMe(scriptElem){
    return scriptElem.getAttribute('src') === "//example.com/embed.js";
}

这继承了任何方法的优点和问题,但不依赖querySelector()于旧浏览器。

6.获取最后执行的脚本

由于脚本是按顺序执行的,最后一个脚本元素通常是当前正在运行的脚本:

<script>
var scripts = document.getElementsByTagName( 'script' );
var me = scripts[ scripts.length - 1 ];
</script>

好处

  • 简单的。
  • 几乎普遍支持
  • 不需要自定义属性或 ID

问题

  • 难道不是异步脚本工作(deferasync
  • 难道不是与动态插入脚本工作
谢谢大家,但你知道我在接受答案4后才回答,对 :)
2021-03-17 02:33:20
“document.currentScript”对动态加载的脚本不起作用,在最新的 chrome/firefox 中返回 null,“上次执行的脚本”工作正常
2021-03-22 02:33:20
不工作的时候script是在template一个影子DOM插入
2021-03-25 02:33:20
同意@RoyiNamir。这是最好的答案。
2021-03-29 02:33:20
这应该是答案。
2021-04-07 02:33:20

由于脚本是顺序执行的,在此之前,当前执行的脚本标签始终是页面上的最后一个脚本标签。因此,要获取脚本标记,您可以执行以下操作:

var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];
当您在页面加载后加载脚本时,它不起作用。你可能不会得到正确的标签。
2021-03-20 02:33:20
这是个好主意,通常对我有用。但我应该补充一点,有时我发现它返回对不同脚本的引用。不知道为什么 - 一直无法追踪到。因此,我通常采用不同的方法,例如,我对脚本文件的名称进行硬编码,然后查找具有该文件名的脚本标记。
2021-04-01 02:33:20
这是简单而优雅的。如果您解压 javascript,在新的 Google Charts/Visualizations API 中有一个示例。他们从脚本标签中加载 JSON 数据,请参阅: ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js
2021-04-04 02:33:20
我能想到的一个例子是将脚本标记异步添加到 DOM 时可能会返回不正确的结果。
2021-04-04 02:33:20
是的,这可能会产生不可预测的结果,因此您可以尝试使用选择器: $('script[src*="/mysource.js"]') ???
2021-04-08 02:33:20

可能最简单的方法是为您的脚本标签指定一个id属性。

虽然你是对的,但在很多情况下 OP 的问题是有效的,有几种情况:1)当你爬行时 2)当你使用客户端的 DOM 时,他不愿意改变
2021-03-24 02:33:20

这是一个 polyfill,它利用document.CurrentScript它是否存在并回退到通过 ID 查找脚本。

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

如果您在每个脚本标签的顶部都包含它,我相信您将能够始终如一地知道哪个脚本标签被触发,并且您还能够在异步回调的上下文中引用脚本标签。

未经测试,因此如果您尝试,请为其他人留下反馈。

但是,该id属性元素中无效script这种方法会产生什么样的问题?
2021-03-12 02:33:20
@nr - 不,所有元素都可以有一个id属性。id, class, 和slot是在 DOM 级别而不是 HTML 级别定义的。如果您转到HTML 中全局属性并滚动列表,您会发现“DOM 标准为任何命名空间中的任何元素定义了类、id 和槽属性的用户代理要求”。后跟“可以在所有 HTML 元素上指定 class、id 和 slot 属性。” DOM 规范在这里涵盖了它
2021-03-21 02:33:20

仅当它们没有“延迟”或“异步”属性时,脚本才会按顺序执行。在这些情况下,了解脚本标记的可能 ID/SRC/TITLE 属性之一也可以工作。所以格雷格和贾斯汀的建议都是正确的。

document.currentScriptWHATWG 列表中已经有一个提案

编辑:Firefox > 4 已经实现了这个非常有用的属性,但它在 IE11 中不可用,我最后检查过,仅在 Chrome 29 和 Safari 8 中可用。

编辑:没有人提到“document.scripts”集合,但我相信以下可能是获取当前正在运行的脚本的一个很好的跨浏览器替代方案:

var me = document.scripts[document.scripts.length -1];
它是 document.scripts 不是 document.script
2021-03-17 02:33:20