JavaScript如何在类内部获取实例化该类的所有脚本文件名
结论
纯标准ECMAScript没有提供对应API,无法无侵入、100%准确实现这个需求。但结合运行环境特性、构建工具或者少量代码约定,可以拿到符合预期的结果,不同方案的适用场景和侵入性不一样。
Node.js ESM环境 零额外依赖方案
直接在类的构造函数里拿错误调用栈解析就行,不需要装任何第三方包:
// 你的自定义类文件,比如 utils/MyClass.js class MyClass { // 用Set存储,自动去重 static createdFrom = new Set() constructor() { // 临时生成错误对象拿调用栈 const stack = new Error().stack.split('\n') // 栈结构:第1行是Error信息,第2行是当前构造函数自身,从第3行开始找外部调用方 for (let i = 2; i < stack.length; i++) { const line = stack[i].trim() // 匹配Node栈里的文件路径,兼容带括号包裹、不带括号两种栈格式 const match = line.match(/\((file:\/\/\/.+):\d+:\d+\)/) || line.match(/at (file:\/\/\/.+):\d+:\d+/) if (match) { const callerPath = match[1] // 排除类自身文件里创建实例的情况 if (callerPath !== import.meta.url) { MyClass.createdFrom.add(callerPath) break } } } // 剩下的构造函数逻辑正常写即可 } } export default MyClass
- 这个方案拿到的是直接执行
new MyClass()的脚本的绝对文件路径,如果实例是封装在某个工厂函数里创建的,拿到的是工厂函数所在文件,不是最终使用实例的文件。 - 代码如果被压缩、或者经过转译改写了栈结构,匹配准确率会下降,开发环境使用完全没问题。
- CommonJS环境把
import.meta.url换成__filename,调整下路径匹配规则就能用。
浏览器环境实现方案
浏览器原生没有暴露脚本文件路径的API,纯运行时拿不到准确文件名,必须配合构建工具:
- Vite、Webpack这类构建工具会在编译阶段给每个模块注入
import.meta.url或者__filename常量,可以直接拿到模块自身的编译后路径 - 复用上面的错误栈解析逻辑,匹配调用方的路径即可
- 如果不想解析栈,也可以写个简单的Babel插件,在所有导入这个类的文件顶部自动加一行注册代码,把当前文件路径传给类的静态注册方法,准确率更高,但需要改构建配置。
跨环境通用 约定式方案
如果不想依赖环境API或者构建流程,直接加个简单约定就行,兼容性拉满:
class MyClass { static createdFrom = new Set() // 要求new实例的时候传入当前文件名作为标识 constructor(fileName) { if (fileName) MyClass.createdFrom.add(fileName) // 其他业务逻辑 } } // 其他文件调用时 // src/page/home.js const ins = new MyClass('home.js') // src/utils/request.js const ins2 = new MyClass('request.js')
缺点是需要所有创建实例的地方都遵守传参约定,侵入性高,适合小项目用。
内容的提问来源于stack exchange,提问作者dreygur
相关产品推荐
相关产品推荐

