如何实时查看JavaScript调用栈内的函数名与调用数量
实现方法
不需要依赖栈溢出触发,JavaScript 原生支持实时获取当前调用栈:实例化一个Error对象,读取它的stack属性就能拿到当前完整的栈帧信息,解析后即可统计每个函数在栈中的调用次数,随时调用随时出结果。
核心实现代码
先封装通用的栈统计工具,自动解析栈帧、统计各函数调用次数:
function countStackCalls() { // 截取栈内容,跳过当前工具函数自身的2层栈帧 const stackFrames = new Error().stack.split('\n').slice(2); const callCount = {}; stackFrames.forEach(frame => { // 匹配栈帧里的函数名,兼容普通函数、箭头函数、对象方法场景 const matchRes = frame.trim().match(/at\s+([^\s(]+)/); let funcName = matchRes ? matchRes[1] : '<anonymous>'; // 处理obj.foo这类对象方法格式,提取最终方法名 if (funcName.includes('.')) funcName = funcName.split('.').pop(); callCount[funcName] = (callCount[funcName] || 0) + 1; }); return callCount; }
适配示例场景的用法
把工具函数和给出的示例代码结合,就能按要求输出统计结果:
var mod = function () { var obj = { foo: (fn) => { // 函数执行时实时取当前栈统计 const stackCount = countStackCalls(); console.log("Function: " + fn + ", nbr of calls in the stack: " + stackCount[fn]); return "My name is: " + fn }, bar: (fn) => { const stackCount = countStackCalls(); console.log("Function: " + fn + ", nbr of calls in the stack: " + stackCount[fn]); return "My name is: " + fn } }; console.log(((fn) => obj[fn](fn))("foo")); console.log(((fn) => obj[fn](fn))("bar")); }; mod();
运行说明
- 上述代码运行时会实时输出当前栈中对应函数的调用次数,不需要等栈溢出。如果是递归调用场景,比如
foo递归调用自身22次,输出结果就会显示Function: foo, nbr of calls in the stack: 22,和期望的输出格式完全一致。 - 不同JS运行环境(Chrome/Firefox/不同版本Node.js)的栈字符串格式有细微差异,生产环境使用时可以根据实际运行环境微调栈帧解析的正则规则,匹配准确率更高。
- 匿名函数会被统一标记为
<anonymous>,如果需要更精准的统计,建议给需要追踪的函数设置明确的函数名,或者像示例一样通过入参传递函数名标识,统计结果会更准确。
内容的提问来源于stack exchange,提问作者user2847853
相关产品推荐
相关产品推荐

