【问题标题】:JavaScript - How do I get the URL of script being called?JavaScript - 如何获取被调用脚本的 URL?
【发布时间】:2010-06-04 18:13:43
【问题描述】:

我将 myscript.js 包含在文件 http://site1.com/index.html 中,如下所示:

<script src=http://site2.com/myscript.js></script>

在“myscript.js”中,我想访问 URL“http://site2.com/myscript.js”。我想要这样的东西:

function getScriptURL() {
    // something here
    return s
}

alert(getScriptURL());

如果从上面提到的 index.html 调用,它会提醒“http://site2.com/myscript.js”。

【问题讨论】:

标签: javascript


【解决方案1】:

来自http://feather.elektrum.org/book/src.html

var scripts = document.getElementsByTagName('script');
var index = scripts.length - 1;
var myScript = scripts[index];

变量 myScript 现在具有脚本 dom 元素。您可以使用myScript.src获取src url。

请注意,这需要作为脚本初始评估的一部分执行。如果您不想污染 Javascript 命名空间,您可以执行以下操作:

var getScriptURL = (function() {
    var scripts = document.getElementsByTagName('script');
    var index = scripts.length - 1;
    var myScript = scripts[index];
    return function() { return myScript.src; };
})();

【讨论】:

  • 在所有浏览器中,这是否总是返回正确脚本的 URL?这看起来会返回最后一个脚本标签,但是如果文档中有多个脚本标签怎么办?
  • 好吧...我的问题是,所有浏览器是否总是完全加载并执行远程脚本的完整内容,然后再转到下一个脚本标签?这个标准化有多严格?我可以想象它同时发生......
  • 要求脚本完全按顺序运行,因为如果脚本标签包含 document.write 会发生什么情况。这就是建议将脚本放在页面底部的原因,因为它们实际上会阻止其他内容的加载。也就是说,HTML5 使用 async 和 defer 属性对其进行了修改:whatwg.org/specs/web-apps/current-work/multipage/…
  • 如果您在页面加载后使用以下方式加载脚本,这将不起作用:document.getElementsByTagName("head")[0].appendChild(scriptElement);
  • 我遇到过这种算法不能可靠运行的情况。设置为异步的其他脚本标签可以在您的脚本被请求和运行之间运行。这些脚本可以将其他脚本添加到出现在您之后的 DOM 中。当您的脚本运行时,页面上的最后一个脚本不再属于您,并返回错误的src
【解决方案2】:

您可以将 id 属性添加到您的脚本标签(即使它在头标签内):

<script id="myscripttag" src="http://site2.com/myscript.js"></script>

然后访问它的src如下:

document.getElementById("myscripttag").src

当然,包含您的脚本的每个文档的 id 值都应该相同,但我认为这不会给您带来很大的不便。

【讨论】:

  • 此答案应标记为“已接受”,因为它涵盖了您在“全局”脚本上下文或“异步”脚本中调用方法时的情况,并且它不依赖于浏览器实现。
  • 请注意,.src 可以返回绝对路径,即使指定了相对路径。你可以使用.getAttribute('src')
【解决方案3】:

除了 IE 都支持

document.currentScript

【讨论】:

【解决方案4】:

简单直接的解决方案,效果很好:

如果不是 IE 你可以使用document.currentScript
对于 IE 你可以做document.querySelector('script[src*="myscript.js"]')
所以:

function getScriptURL(){
 var script =  document.currentScript || document.querySelector('script[src*="myscript.js"]')
 return script.src
}
更新

在模块脚本中,您可以使用:

 import.meta.url

mdn中所述

【讨论】:

    【解决方案5】:

    我编写了一个类来查找使用延迟加载和异步脚本标签的脚本路径。

    我有一些与我的脚本相关的模板文件,因此我没有对它们进行硬编码,而是创建了类来自动创建路径。 The full source is here on github.

    不久前我曾使用 arguments.callee 尝试做类似的事情,但我最近在 MDN 上看到它是 not allowed in strict mode

    function ScriptPath() {
      var scriptPath = '';
      try {
        //Throw an error to generate a stack trace
        throw new Error();
      }
      catch(e) {
        //Split the stack trace into each line
        var stackLines = e.stack.split('\n');
        var callerIndex = 0;
        //Now walk though each line until we find a path reference
        for(var i in stackLines){
          if(!stackLines[i].match(/http[s]?:\/\//)) continue;
          //We skipped all the lines with out an http so we now have a script reference
          //This one is the class constructor, the next is the getScriptPath() call
          //The one after that is the user code requesting the path info (so offset by 2)
          callerIndex = Number(i) + 2;
          break;
        }
        //Now parse the string for each section we want to return
        pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/);
      }
    
      this.fullPath = function() {
        return pathParts[1];
      };
    
      this.path = function() {
        return pathParts[2];
      };
    
      this.file = function() {
        return pathParts[3];
      };
    
      this.fileNoExt = function() {
        var parts = this.file().split('.');
        parts.length = parts.length != 1 ? parts.length - 1 : 1;
        return parts.join('.');
      };
    }
    

    【讨论】:

    • 在这里聚会有点晚了,但我正在尝试这段代码 sn-p 并发现它在 for 循环中将 2 添加到当前索引的部分“callerIndex = Number(i) + 2;"似乎 break 是不必要的,并导致它不起作用。简单地消除“+ 2”就可以了。是否有我误解的内容或其他需要 + 2 的情况?
    • 你不需要以这种方式抛出“Error”(得到它的“.stack”)它只是一个像其他对象一样的对象:console.log(new Error().stack);
    • 感谢您提出这个想法,并感谢@AbdullahAydın 提出防止投掷的想法。那么我想下面的单行就可以了,不是吗? var scriptUrl = new Error().stack.match(/@(https?:\/\/.+):\d+:\d+/)[1]
    • 另外@Pierre-Antoine 请记住 Error.prototype.stack 属性是非标准的:/您应该小心使用它。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • @AbdullahAydın:请注意,在抛出错误之前,新错误的堆栈属性不会填充到 IE 和 Edge 浏览器中。
    【解决方案6】:

    如果你有机会使用 jQuery,代码应该是这样的:

    $('script[src$="/myscript.js"]').attr('src');
    

    【讨论】:

    • 它是否适用于延迟、异步和延迟加载脚本?
    • 它只是在 DOM 中查找带有 src "/myscript.js" 的脚本标签。其他属性无关紧要
    • 要将它与 wordpress 一起使用到附加版本的任何其他位置,您应该使用 $('script[src*="/myscript.js"]').attr('src');这样它将忽略脚本末尾的 ?ver=2.3.3 。无论结尾是什么,* 都会使其继续工作。
    【解决方案7】:

    以下代码可让您找到具有给定名称的脚本元素

    var scripts = document.getElementsByTagName( 'script' );
            var len = scripts.length
            for(var i =0; i < len; i++) {
                if(scripts[i].src.search("<your JS file name") > 0 && scripts[i].src.lastIndexOf("/") >= 0) {
                    absoluteAddr = scripts[i].src.substring(0, scripts[i].src.lastIndexOf("/") + 1);
                    break;
                }
            }
    

    【讨论】:

    • 现在使用 querySelector() 似乎会更短一些,而且可能更快。
    【解决方案8】:
    document.currentScript.src
    

    将返回当前脚本 URL 的 URL。

    注意:如果你加载了Module类型的脚本,那么使用

    import.meta.url
    

    更多import.metacurrentScript.src

    【讨论】:

      【解决方案9】:

      一些死灵术,但这里有一个尝试几种方法的函数

      function getScriptPath (hint) {
          if (  typeof document === "object" && 
                typeof document.currentScript === 'object' && 
                document.currentScript && // null detect
                typeof document.currentScript.src==='string' && 
                document.currentScript.src.length > 0) {
              return document.currentScript.src;
          }
          
          
          let here = new Error();
          if (!here.stack) {
              try { throw here;} catch (e) {here=e;}
          }
          if (here.stack) {
              
              const stacklines = here.stack.split('\n');
              console.log("parsing:",stacklines);
              let result,ok=false;
              stacklines.some(function(line){
                  if (ok) {
                     const httpSplit=line.split(':/');
                     const linetext = httpSplit.length===1?line.split(':')[0]:httpSplit[0]+':/'+( httpSplit.slice(1).join(':/').split(':')[0]);
                     const chop = linetext.split('at ');
                     if (chop.length>1) {
                         result = chop[1];
                         if ( result[0]!=='<') {
                            console.log("selected script from stack line:",line);               
                            return true;
                         }
                         result=undefined;
                     }
                     return false; 
                  }
                  ok = line.indexOf("getScriptPath")>0;
                  return false;
              });
              return result;
          }
          
          if ( hint && typeof document === "object") {
             const script = document.querySelector('script[src="'+hint+'"]');
             return script && script.src && script.src.length && script.src;
          }
          
      }
         
         console.log("this script is at:",getScriptPath ())

      【讨论】:

        【解决方案10】:

        你不能使用 location.href 或 location.host 然后附加脚本名称吗?

        【讨论】:

        • 这行不通,因为脚本在site1.com/index.html 页面中运行。因此,即使脚本是从 site2.com 加载的,如果您从脚本中访问位置,它也会返回“site1.com/index.html”...
        • 之前的评论可能不够清楚,但 location.href 是当前页面的 URL。该脚本可能位于 /scripts/script.js 之类的子目录中,甚至可能是外部目录。如果需要获取当前脚本的 URL,那么通常有一个严重的原因,而真正简单的页面 URL 将没有任何帮助。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-11
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 2017-08-22
        • 1970-01-01
        相关资源
        最近更新 更多