Node.js中如何记录变量被修改为NaN时的调用栈?
Node.js中如何记录变量被修改为NaN时的调用栈?
嗨,这个问题我之前排查bug时也碰到过!要追踪变量被改成NaN的调用栈,完全不用大动干戈,Node.js环境下有几个轻量的方案,改动极小就能实现:
方法一:用原生Getter/Setter监听(无需额外依赖)
我们可以用Object.defineProperty把变量封装成一个带监听的属性,每次赋值都会触发setter函数,这样就能在赋值时检查是否为NaN,一旦触发就打印调用栈。
代码示例:
// 用一个内部变量存实际值 let _foo = 0; // 把foo挂载到全局(或者你当前的作用域对象上),添加监听 Object.defineProperty(globalThis, 'foo', { get() { return _foo; }, set(value) { // 检测是否被设置为NaN if (Number.isNaN(value)) { console.error('⚠️ foo被设置为NaN了!调用栈如下:'); console.error(new Error().stack); } _foo = value; } }); // 你原来的代码几乎不用改,直接使用foo即可 for (foo = 0; foo < 5; foo++) { // 模拟某个逻辑把foo改成NaN if (foo === 3) { foo = NaN; } } if (isNaN(foo)) { console.log('已检测到foo为NaN'); }
这种方式只需要替换原来的let foo定义,其余业务代码完全不用调整,非常适合快速排查问题。new Error().stack会完整打印出赋值操作的调用栈,帮你精准定位到哪一行代码搞的鬼。
方法二:用NPM包简化监听(代码更简洁)
如果觉得手动写defineProperty有点麻烦,可以用现成的监听工具包,比如watchjs:
- 先安装依赖:
npm install watchjs
- 代码示例:
const watch = require('watchjs').watch; // 把变量放到对象里(watchjs更适合监听对象属性) const state = { foo: 0 }; // 监听foo的变化 watch(state, 'foo', (prop, action, newValue) => { if (Number.isNaN(newValue)) { console.error('⚠️ foo被设置为NaN了!调用栈如下:'); console.error(new Error().stack); } }); // 业务代码改成访问state.foo for (state.foo = 0; state.foo < 5; state.foo++) { if (state.foo === 3) { state.foo = NaN; } } if (isNaN(state.foo)) { console.log('已检测到foo为NaN'); }
这个方案代码更简洁,适合需要监听多个变量的场景,不过需要额外安装依赖。
备注:内容来源于stack exchange,提问作者Mart
相关产品推荐
相关产品推荐

