JavaScript实现全局GetThisFileName函数获取当前执行文件名是否可行?
是否可以实现全局
GetThisFileName函数获取执行时所在文件名 可以实现,不同运行环境的实现逻辑有差异,以下是不同场景的实现方案:
Node.js 环境实现
Node.js 中可以通过捕获调用栈信息来获取调用方所在的文件路径,再提取文件名即可:
// 全局挂载函数 global.GetThisFileName = function() { // 捕获调用栈 const stackTrace = new Error().stack; // 按行拆分调用栈:第一行是Error信息,第二行是当前函数自身的调用,第三行就是调用方的位置 const callerLine = stackTrace.split('\n')[2]; // 匹配文件路径,Node.js调用栈格式一般为 at 函数名 (文件路径:行号:列号) / 或者直接 at 文件路径:行号:列号 const filePathMatch = callerLine.match(/\((.*):\d+:\d+\)$/) || callerLine.match(/at (.*):\d+:\d+$/); if (!filePathMatch) return null; // 提取文件名,兼容Windows和Unix路径分隔符 const filePath = filePathMatch[1]; return filePath.split(/[\\/]/).pop(); }
注意:如果调用方是Node.js内置模块、eval执行的代码,或者代码被压缩/混淆过,可能会出现匹配失败的情况,返回
null。
测试示例:
- 函数定义在
abc.js中,在def.js里调用GetThisFileName(),返回def.js - 在
somefile.js里调用,返回somefile.js
浏览器环境实现
浏览器环境的实现逻辑类似,也是通过调用栈匹配加载的JS文件名,不过浏览器的调用栈格式和Node.js有细微差别,需要调整匹配规则:
// 全局挂载函数 window.GetThisFileName = function() { const stackTrace = new Error().stack; const callerLine = stackTrace.split('\n')[2]; // 匹配浏览器调用栈中的JS文件路径,浏览器路径一般是完整URL const filePathMatch = callerLine.match(/\((.*):\d+:\d+\)$/) || callerLine.match(/@(.*):\d+:\d+$/); if (!filePathMatch) return null; const filePath = filePathMatch[1]; // 去掉URL的查询参数和哈希,提取文件名 const fileNamePart = filePath.split(/[\\/]/).pop().split('?')[0].split('#')[0]; return fileNamePart || null; }
注意:如果JS是内联在HTML中的代码、通过eval执行,或者开启了SourceMap映射到源文件,返回结果可能和实际加载的文件名不一致。如果网站开启了内容安全策略(CSP)禁止捕获调用栈,该函数会失效。
已知限制
- 代码经过打包工具(如Webpack、Vite、Rollup)打包后,所有JS代码会被合并到一个或多个bundle文件中,此时调用该函数只会返回打包后的bundle文件名,无法返回源码的原始文件名。如果需要在打包后仍能获取原始文件名,需要配合打包工具的
__filename常量注入配置使用。 - 严格模式下调用栈的格式不会发生变化,不影响该函数的运行。
内容的提问来源于stack exchange,提问作者Fr3d Fields
相关产品推荐
相关产品推荐

