【问题标题】:javascript circular reference - breaking the cyclejavascript循环引用 - 打破循环
【发布时间】:2016-12-27 20:24:38
【问题描述】:

例如,我有这样的代码:

var objectA = {};
var objectB = {};

objectA.pointer = objectB;
objectB.pointer = objectA;

objectA = null;
objectB = null;

我假设在最后两个语句之后,没有对最初分配给 objectA 和 objectB 变量的对象的引用。但根据技术文献,这些对象的参考仍然存在。为什么 ? objectA.pointer 引用或 objectB.pointer 引用是否仍然存在,即使 objectA 和 objectB 设置为 null ?

【问题讨论】:

  • objectA = null; 仅将 变量 objectA 的值设置为 null。它不会更改 property objectB.pointer 的值。 objectB.pointer 仍然指的是一个对象。变量/属性只是值的容器。分配“复制”该值,现在两个容器包含“相同”值(每个都有自己的副本)。替换其中一个容器中的值不会神奇地替换另一个容器中的值。
  • objectA 设置为null 不会改变objectB.pointer
  • @FelixKling:如果 objectB 设置为 null,objectB.pointer 如何引用该对象?
  • 同样,变量和属性是容器。当您执行objectB.pointer = objectA; 时,您将 content 从一个容器复制到另一个容器。换句话说,objectB.pointernot 指的是 container objectA 而是指它拥有/拥有的 value。稍后当您执行 objectA = null; 时,您正在更改 container objectAcontent。这对objectB.pointer 没有影响。这是一个更简单的示例:var foo = 42; var bar = foo; foo = 0;。即使我将 foo 设置为 0bar 仍然具有 42 的值。更改foo 的值对bar 没有影响。
  • @FelixKling 我了解原始值和参考值之间的复制是如何工作的。我在说的是:在我的示例中有两个对象。一开始他们有一个引用——第一个对象在objectA中有引用,第二个对象在objectB中有引用。然后为这些对象创建第二个引用。第一个对象在 objectB.pointer 中有第二个引用,第二个对象在 objectA.pointer 中有第二个引用。那么我们如何将两个对象的引用减少到零呢?我假设这是通过将 objectA 和 objectB 都设置为 null 来实现的。

标签: javascript circular-reference


【解决方案1】:

即使 objectAobjectB 设置为 nullobjectA.pointer 引用或 objectB.pointer 引用仍然存在吗?

是的。

也许一些 ASCII 艺术有帮助。执行后

var objectA = {};
var objectB = {};

环境包含两个变量(objectAobjectA),它们持有对两个对象(表示为 ref:XXX)的引用:

                          +--------------+
+-------+---------+  +--->|  Object#123  |
|objectA|ref:123 *+--+    +--------------+
+-------+---------+                       
|objectB|ref:456 *+--+    +--------------+
+-------+---------+  +--->|  Object#456  |
                          +--------------+

为对象添加属性后,

objectA.pointer = objectB;
objectB.pointer = objectA;

两个对象都有一个pointer 属性,每个都包含对另一个对象的引用:

                         +-----------------+      
                         |   Object#123    |      
                    +--->+-------+---------+<----+
+-------+---------+ |    |pointer|ref:456 *+---+ |
|objectA|ref:123 *+-+    +-------+---------+   | |
+-------+---------+                            | |
|objectB|ref:456 *+-+    +-----------------+   | |
+-------+---------+ |    |   Object#456    |   | |
                    +--->+-------+---------+<--+ |
                         |pointer|ref:123 *+-----+
                         +-------+---------+      

如您所见,pointer 属性与objectAobjectB 变量之间没有关系。 objectA.pointer 没有引用变量 objectB,它获得了其值的副本 (ref:456),即对对象的引用。

将两个变量都设置为null后,

objectA = null;
objectB = null;

环境如下:

                         +-----------------+      
                         |   Object#123    |      
                         +-------+---------+<----+
+-------+---------+      |pointer|ref:456 *+---+ |
|objectA|  null   |      +-------+---------+   | |
+-------+---------+                            | |
|objectB|  null   |      +-----------------+   | |
+-------+---------+      |   Object#456    |   | |
                         +-------+---------+<--+ |
                         |pointer|ref:123 *+-----+
                         +-------+---------+      

pointer 属性仍然保存对另一个对象的引用。替换 objectAobjectB 的值并没有改变这一点。

【讨论】:

  • 哦美丽的 ascii 艺术!谢谢,这个解释得很好。我现在清楚地理解了这个问题。我是盲人:) 再次感谢
【解决方案2】:

您不必担心这一点,JS 是一种托管语言,并且有一个内置的Garbage Collector,它将处理这种情况。在这里阅读更多:https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

您所描述的问题已通过各种技术解决。你可以在这个问题How does Java Garbage Collection work with Circular References? 中阅读关于它在Java 中的实现。

【讨论】:

    猜你喜欢
    • 2018-02-28
    • 2016-01-01
    • 1970-01-01
    • 2013-08-03
    • 2021-03-11
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多