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

2022-01-29 00:00:00 element parent javascript

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

How can I reference the script element that loaded the javascript that is currently running?

情况是这样的.我在页面高处加载了一个主"脚本,首先在 HEAD 标记下.

Here's the situation. I have a "master" script being loaded high in the page, first thing under the HEAD tag.

<!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 元素尚未完成渲染:

There is a script in "scripts.js" which needs to be able to do on-demand loading of other scripts. The normal method doesn't quite work for me because I need to add new scripts without referencing the HEAD tag, because the HEAD element hasn't finished rendering:

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

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

What I want to do is reference the script element that loaded the current script so that I can then append my new dynamically loaded script tags into the DOM after it.

<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>

推荐答案

如何获取当前脚本元素:

1.使用 document.currentScript

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

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

好处

  • 简单明了.可靠.
  • 无需修改脚本标签
  • 适用于异步脚本(defer & async)
  • 使用动态插入的脚本
    • 不适用于旧版浏览器和 IE.
    • 不适用于模块 <script type="module">

    为脚本提供一个 id 属性将使您可以使用 document.getElementById().

    Giving the script an id attribute will let you easily select it by id from within using document.getElementById().

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

    好处

    • 简单明了.可靠.
    • 几乎普遍支持
    • 适用于异步脚本(defer & async)
    • 使用动态插入的脚本
      • 需要向脚本标签添加自定义属性
      • id 属性可能会在某些边缘情况下导致某些浏览器中的脚本出现奇怪的行为
      • Requires adding a custom attribute to the script tag
      • id attribute may cause weird behaviour for scripts in some browsers for some edge cases

      给脚本一个 data-* 属性将让您轻松地从内部选择它.

      Giving the script a data-* attribute will let you easily select it from within.

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

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

      This has few benefits over the previous option.

      • 简单明了.
      • 适用于异步脚本(defer & async)
      • 使用动态插入的脚本
      • 需要向脚本标签添加自定义属性
      • HTML5 和 querySelector() 并非在所有浏览器中都兼容
      • 没有使用 id 属性得到广泛支持
      • 将绕过 <script>id 边缘情况.
      • 如果页面上的另一个元素具有相同的数据属性和值,可能会感到困惑.
      • Requires adding a custom attribute to the script tag
      • HTML5, and querySelector() not compliant in all browsers
      • Less widely supported than using the id attribute
      • Will get around <script> with id edge cases.
      • May get confused if another element has the same data attribute and value on the page.

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

      Instead of using the data attributes, you can use the selector to choose the script by source:

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

      在 embed.js 中:

      In embed.js:

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

      好处

      • 可靠
      • 适用于异步脚本(defer & async)
      • 使用动态插入的脚本
      • 无需自定义属性或 ID
        • 不适用于本地脚本
        • 会在开发和生产等不同的环境中引起问题
        • 静态且易碎.更改脚本文件的位置需要修改脚本
        • 没有使用 id 属性得到广泛支持
        • 如果两次加载相同的脚本会导致问题
        • Does not work for local scripts
        • Will cause problems in different environments, like Development and Production
        • Static and fragile. Changing the location of the script file will require modifying the script
        • Less widely supported than using the id attribute
        • Will cause problems if you load the same script twice

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

        We can also loop over every script element and check each individually to select the one we want:

        <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() 属性的旧浏览器中使用之前的两种技术.例如:

        This lets us use both previous techniques in older browsers that don't support querySelector() well with attributes. For example:

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

        这继承了所采用的任何方法的优点和问题,但不依赖于 querySelector(),因此可以在旧浏览器中使用.

        This inherits the benefits and problems of whatever approach is taken, but does not rely on querySelector() so will work in older browsers.

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

        Since the scripts are executed sequentially, the last script element will very often be the currently running script:

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

        好处

        • 简单.
        • 几乎普遍支持
        • 无需自定义属性或 ID
          • 不是否适用于异步脚本(defer & async)
          • 不是否适用于动态插入的脚本
          • Does not work with asynchronous scripts (defer & async)
          • Does not work with scripts inserted dynamically

相关文章