已关闭严格模式仍报错:TypeScript提示无法访问函数的callee
问题描述
我习惯在调试、性能分析或熟悉代码时,在应用里随处插入自定义日志函数,用arguments.callee.name自动获取所在函数名,不用手动输入——只需要粘贴myProfilingFunc(arguments.callee.name);就行。这种方式在非严格模式的JavaScript里正常运行,但在TypeScript里却报错:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
就算在tsconfig.json里关闭了所有严格相关选项(包括strict、alwaysStrict设为false,noImplicitUseStrict设为true),问题还是存在。这个功能2019年还能用,现在突然失效了。最小复现代码如下:
function testCallee() { console.log(arguments.callee.name); } testCallee();
解决方案
为什么原来的方法失效了
即使关闭了TypeScript的严格编译选项,现代JavaScript运行环境(浏览器、Node.js等)可能默认对模块代码启用严格模式,而arguments.callee在严格模式下是被明确禁用的,所以不管编译选项怎么设,运行时都会报错。此外,TypeScript新版本的编译逻辑调整,也可能导致相关代码被自动纳入严格模式范围。
替代方案:通过Error栈追踪获取函数名
可以利用Error对象的栈信息来解析当前执行的函数名,不用依赖arguments.callee:
function getCurrentFunctionName(): string | undefined { const stack = new Error().stack; if (!stack) return undefined; // 解析栈帧,不同环境格式略有差异,这里取调用getCurrentFunctionName的上一层函数 const frame = stack.split('\n')[1].trim(); // 提取函数名,兼容不同浏览器/Node.js的栈格式 const match = frame.match(/at\s+(?:(\w+)\s+\()|at\s+(\w+)/); return match ? (match[1] || match[2]) : undefined; } // 自定义日志函数 function myProfilingFunc() { const funcName = getCurrentFunctionName(); console.log(`[Profiling] 当前函数:${funcName}`); } // 使用示例 function testFunc() { myProfilingFunc(); } testFunc(); // 输出 [Profiling] 当前函数:testFunc
更简洁的写法(针对非箭头函数)
如果你的函数都是普通命名函数,也可以直接利用函数的name属性,不过需要手动传入函数本身:
function myProfilingFunc(func: Function) { console.log(`[Profiling] 当前函数:${func.name}`); } function testFunc() { myProfilingFunc(testFunc); } testFunc(); // 输出 [Profiling] 当前函数:testFunc
这种写法虽然需要手动写函数名,但比栈追踪性能更好,且兼容性更稳定。
TypeScript装饰器方案(适合类方法)
如果是类中的方法,可以用装饰器自动注入日志,完全不用手动写代码:
function Profiled(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function(...args: any[]) { console.log(`[Profiling] 调用方法:${propertyKey}`); return originalMethod.apply(this, args); }; return descriptor; } class TestClass { @Profiled testMethod() { // 业务逻辑 } } const instance = new TestClass(); instance.testMethod(); // 输出 [Profiling] 调用方法:testMethod
内容的提问来源于stack exchange,提问作者Chema
相关产品推荐
相关产品推荐

