我如何从该脚本中获取脚本文件名?

IT技术 javascript html
2021-01-29 15:17:34

我很确定答案是否定的,但我想我还是会问。

如果我的站点引用名为“whatever.js”的脚本,是否可以从该脚本中获取“whatever.js”?喜欢:

var scriptName = ???

if (typeof jQuery !== "function") {
    throw new Error(
        "jQuery's script needs to be loaded before " + 
        scriptName + ". Check the <script> tag order.");
}

可能比依赖检查更麻烦,但到底是什么。

6个回答
var scripts = document.getElementsByTagName('script');
var lastScript = scripts[scripts.length-1];
var scriptName = lastScript.src;
alert("loading: " + scriptName);

测试:FF 3.0.8、Chrome 1.0.154.53、IE6


另请参阅:如何引用加载当前正在执行的脚本的脚本标记?

我遇到过这种算法不能可靠工作的情况。设置为 async 的其他脚本标记可以在您的脚本被请求和运行之间运行。这些脚本可以将其他脚本添加到出现在您的 DOM 之后的 DOM 中。当您的脚本运行时,页面上的最后一个脚本不再是您的脚本,并且src返回错误
2021-03-23 15:17:34
这个答案已经严重过时了。脚本可以是延迟的、异步的、module的、工作者的。这个答案对他们都不起作用。
2021-03-31 15:17:34
极端情况:如果当前脚本是<head><body>加载添加的,并且其中有任何脚本,<body>则将返回 中的最后一个脚本,而<body>不是<head>.
2021-04-03 15:17:34
我觉得document.currentScript应该在这里提到,但就像@gman 所说的那样,这个答案总体上已经过时了,而且该算法没有涵盖很多边缘情况。
2021-04-11 15:17:34

我知道这是旧的,但我开发了一个更好的解决方案,因为以上所有内容都不适用于异步脚本。通过一些调整,以下脚本几乎可以涵盖所有用例。继承人什么对我有用:

function getScriptName() {
    var error = new Error()
      , source
      , lastStackFrameRegex = new RegExp(/.+\/(.*?):\d+(:\d+)*$/)
      , currentStackFrameRegex = new RegExp(/getScriptName \(.+\/(.*):\d+:\d+\)/);

    if((source = lastStackFrameRegex.exec(error.stack.trim())) && source[1] != "")
        return source[1];
    else if((source = currentStackFrameRegex.exec(error.stack.trim())))
        return source[1];
    else if(error.fileName != undefined)
        return error.fileName;
}

不确定对 Internet Explorer 的支持,但在我测试过的所有其他浏览器中都可以正常工作。

谢谢!正是我要找的!有趣的是,有时在 python 或 Java 代码中会出现与错误堆栈相同的方法。
2021-03-15 15:17:34
非常好的解决方案,遗憾的是它不适用于 IE10-:(
2021-03-15 15:17:34
谢谢!这是一个很好的方法,因为它也适用于 Web Workers。然而,它在缩小后失败,因为该函数不再被称为 getScriptName。解决方案是将 currentStackFrameRegex 表达式替换为: new RegExp(arguments.callee.name + ' \(.+\\/(.*):\\d+:\\d+\)')
2021-03-18 15:17:34
arguments.callee.name如果函数被定义为函数表达式,@MaMazav将不起作用。我认为包罗万象的解决方案将替换arguments.callee.namescriptNamewhere scriptNameis var scriptName = arguments.callee.name || 'getScriptName';当然,如果将函数表达式分配给普通变量,缩小会更改变量名称,因此必须将函数分配给对象键才能使其工作。
2021-03-27 15:17:34
@PsychoWood 如果找到解决方案,我会查看并更新答案。
2021-03-30 15:17:34

您可以使用...

var scripts = document.getElementsByTagName("script"),
  currentScriptUrl = (document.currentScript || scripts[scripts.length - 1]).src;

currentScript() 除 IE 外,所有浏览器都支持。

确保它在文件被解析和执行时运行,而不是在 DOM 准备好或window加载时运行。

如果它是一个空字符串,则您的script块没有或空src属性。

除了@Stephan 的评论之外,caniuse.com 上现在有一个document.currentScript条目
2021-03-19 15:17:34
与答案没有直接关系,但著名的caniuse.com尚未监控document.currentScript然而,已经打开了一个问题。为了让这个功能出现在 caniuse.com 上,你可以投票:github.com/Fyrd/caniuse/issues/1099
2021-04-09 15:17:34
async与其他一些答案不同,我喜欢这甚至在脚本中也很有用不幸的是,如果currentScript在事件处理程序或全局函数中调用它本身是从另一个文件调用的,它将返回另一个文件。
2021-04-11 15:17:34

在 Node.js 中:

var abc = __filename.split(__dirname+"/").pop();
显然 __filename 和 __dirname 是 node.js 的东西,并且只在 node.js 上下文中工作。
2021-03-14 15:17:34
我试过这个,但我得到 __filename is not defined...我用错了吗?
2021-03-25 15:17:34

Shog9 的建议更短:

alert("loading: " + document.scripts[document.scripts.length-1].src);