JavaScript对象循环引用问题:为何以下代码会产生循环引用?
为什么这段代码会产生循环引用?
嘿,我来帮你拆解清楚这段代码里的循环引用到底是怎么回事——核心是JavaScript中引用类型的内存管理逻辑在起作用,咱们一步步看:
代码执行的每一步内存变化
咱们把对象想象成堆内存里的“实体”,变量(比如john、bob)只是指向这些实体的“指针标签”:
var john = {};:在堆里创建一个空对象(咱们叫它对象A),john这个标签就贴在对象A上,指向它。var bob = {};:同理,堆里创建另一个空对象(对象B),bob标签指向对象B。john.friend = bob;:给对象A添加一个friend属性,这个属性的值是bob标签指向的对象——也就是直接把对象B的引用存在对象A里。现在对象A → 对象B。bob.friend = john;:给对象B添加friend属性,值是john标签指向的对象A。这一步完成后,对象B → 对象A,两个对象形成了互相引用的闭环:对象A ↔ 对象B。
为什么john = null没解决循环引用?
当你执行john = null时,只是把john这个“指针标签”给撕了——它不再指向对象A了,但对象A本身并没有被销毁!因为对象B的friend属性还牢牢地引用着对象A,对象A的friend属性也还引用着对象B。
JavaScript的垃圾回收器只会回收那些“没有任何引用指向”的对象,现在这两个对象互相抱着对方,所以都不会被回收。
为什么打印会显示[Circular]?
当你console.log(bob.friend)时,其实是在打印对象A。而对象A的friend属性是对象B,对象B的friend属性又回到了对象A——浏览器/Node.js在遍历这个对象结构时,检测到了这种无限循环的引用,所以用[Circular]来标记这个循环,避免无限递归打印。
简单说就是:你只是扔了指向对象A的标签,但对象A和对象B之间的互相绑定还在,循环引用自然就一直存在啦。
内容的提问来源于stack exchange,提问作者Vinay Bedre
相关产品推荐
相关产品推荐

