我想在正常编程中获取函数调用堆栈而不是异常(不是新的Error()。stack)。
例如,我已经知道单击标记时会调用函数 f ,并且 f 如下:
function f () {
...
f1 (); // f1 is a custom function in another JavaScript file
...
}
现在我有 f 句柄和名称 f1 ,我可以 f1 在哪个文件中调用chrome或puppeteer中的某个函数并获取其行数?
答案 0 :(得分:0)
没有办法抓住浏览器直接使用的普通堆栈(至少没有标准方式,也没有办法让我很难)。这通常位于原生处理部分的内部。最接近的方式是new Error().stack
你已经提到过你不喜欢。
向每个函数添加内容的唯一其他方法是将其自身附加到您维护的堆栈中。
你可以通过创建某种包装函数来实现这一点,如下所示:
const stack = []; // somewhere in the global space
const wrapInStackReporter = realFunc => function () {
stack.push({ func: realFunc, name: realFunc.name, arguments });
realFunc.apply(this, arguments);
stack.pop();
};
然后您就可以使用它:
const someFunc = wrapInStackReporter(() => console.log('doing something'));
然后,您将在全球空间中拥有stack
,以便跟踪正在发生的事情。
你可以更进一步,自动化包装,让它递归循环遍历它可以找到的所有函数(从全局空间开始并从那里开始),这样你就不必手动包装每个函数:
const wrapAll = (target) => {
Object.keys(target).forEach(key => {
if (typeof target[key] == "object" && !(target[key] instanceof Function)) {
wrapAll(target[key]);
} else if(target[key] instanceof Function) {
target[key] = wrapInStackReporter(target[key]);
}
});
};
wrapAll(window || global); // window for browsers, global for Node
上面的代码应该很接近,但可能没有考虑到你所遇到的所有可能的怪异,但它会给你一个大致的想法。你必须小心引起副作用和奇怪的条件(特别是如果你采用自动换行方法)。