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

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

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

当前回答

这是一个利用文档的填充程序。如果存在CurrentScript,则返回到按ID查找脚本。

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

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

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

未经测试,所以如果你尝试了,给别人留下反馈。

其他回答

如果您可以假定脚本的文件名,就可以找到它。到目前为止,我只在Firefox中测试过以下功能。

  function findMe(tag, attr, file) {
    var tags = document.getElementsByTagName(tag);
    var r = new RegExp(file + '$');
    for (var i = 0;i < tags.length;i++) {
      if (r.exec(tags[i][attr])) {
        return tags[i][attr];
      }
    }
  };
  var element = findMe('script', 'src', 'scripts.js');

我有这个,它在FF3, IE6和7中工作。按需加载脚本中的方法直到页面加载完成才可用,但这仍然非常有用。

//handle on-demand loading of javascripts
makescript = function(url){
    var v = document.createElement('script');
    v.src=url;
    v.type='text/javascript';

    //insertAfter. Get last <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}

获取脚本,即当前加载的脚本可以使用

var thisScript = document.currentScript;

您需要在脚本的开头保留一个引用,以便稍后调用

var url = thisScript.src

考虑一下这个算法。当你的脚本加载时(如果有多个相同的脚本),查看文档。脚本,找到第一个具有正确的“src”属性的脚本,并保存它,并使用数据属性或唯一的className将其标记为“visited”。

当加载下一个脚本时,扫描文档。再次执行脚本,传递已经标记为访问过的任何脚本。以该脚本的第一个未访问实例为例。

这假设相同的脚本可能会按照它们加载的顺序执行,从头部到主体,从上到下,从同步到异步。

(function () {
  var scripts = document.scripts;

  // Scan for this data-* attribute
  var dataAttr = 'data-your-attribute-here';

  var i = 0;
  var script;
  while (i < scripts.length) {
    script = scripts[i];
    if (/your_script_here\.js/i.test(script.src)
        && !script.hasAttribute(dataAttr)) {

        // A good match will break the loop before
        // script is set to null.
        break;
    }

    // If we exit the loop through a while condition failure,
    // a check for null will reveal there are no matches.
    script = null;
    ++i;
  }

  /**
   * This specific your_script_here.js script tag.
   * @type {Element|Node}
   */
  var yourScriptVariable = null;

  // Mark the script an pass it on.
  if (script) {
    script.setAttribute(dataAttr, '');
    yourScriptVariable = script;
  }
})();

这将扫描所有脚本,查找第一个没有标记特殊属性的匹配脚本。

然后,如果找到该节点,就用data-属性标记它,这样后续扫描就不会选择它。这类似于图遍历BFS和DFS算法,其中节点可能被标记为“已访问”以防止重访。

这是一个利用文档的填充程序。如果存在CurrentScript,则返回到按ID查找脚本。

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

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

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

未经测试,所以如果你尝试了,给别人留下反馈。