如何从JS对象获取循环引用数据?属性访问与序列化问题求助
解决console.log能看到属性但直接访问返回undefined+循环引用无法JSON序列化的问题
兄弟我太懂这种糟心的情况了——控制台明明显示对象有err属性,伸手去拿却摸空,还碰上个循环引用的报错!咱们一步步来拆解:
先搞懂为什么console.log能看到但访问不到
浏览器/Node的控制台对对象是惰性求值的:你打印对象时,它只是记录了一个引用,等你展开看的时候才会去读取最新的属性状态。这就导致一种坑:你打印的时候err还没被赋值,等你展开控制台时,异步操作完成了属性才加上,所以看起来“能看到但拿不到”。
第一步:确认属性真的存在(或存在时机)
先别急着处理循环引用,先验证这个err到底是不是真的在你访问的时候存在:
// 打印当前对象的所有可枚举键 console.log(Object.keys(runnable)); // 严格检查对象自身是否拥有这个属性 console.log(Object.hasOwn(runnable, 'err'));
如果这两个输出里都没有err,那基本就是属性是你打印之后才被动态添加的,这时候得去排查代码里给runnable.err赋值的逻辑是不是异步的——比如在回调、Promise里,你访问的时候赋值还没完成。
不用JSON.stringify也能查看带循环引用的完整对象
JSON.stringify搞不定循环引用很正常,但我们有更靠谱的工具:
浏览器端:直接复制控制台对象
在控制台里找到打印出的runnable对象,右键它 → 选择「Copy object」,然后粘贴到编辑器里,就能拿到带循环引用标记的完整对象结构了,比JSON.stringify好用多了。
Node.js端:用util.inspect
Node内置的util模块专门用来处理这种情况,它能识别循环引用并标记,还能显示隐藏属性:
const util = require('util'); console.log(util.inspect(runnable, { depth: null, // 递归显示所有层级 showHidden: true, // 显示不可枚举属性 showCircular: true // 明确标记循环引用 }));
如果属性是不可枚举的怎么办?
有些对象的属性是被设置为不可枚举的,普通的.访问或者Object.keys看不到,但控制台会显示。这时候可以用:
// 获取属性描述符,看是不是不可枚举 console.log(Object.getOwnPropertyDescriptor(runnable, 'err')); // 直接反射获取属性,不管是否可枚举 console.log(Reflect.get(runnable, 'err'));
总结一下排查流程
- 用
Object.hasOwn和Object.keys确认访问时机err是否存在; - 用浏览器DevTools的「Copy object」或Node的
util.inspect查看完整对象(包括循环引用); - 排查是否是异步赋值导致的访问时机问题;
- 检查属性是否为不可枚举类型。
内容的提问来源于stack exchange,提问作者Nick Maddren
相关产品推荐
相关产品推荐

