通过引用复制到第二个属性的对象即使在删除原始属性后仍然存在?

时间:2014-10-27 08:38:23

标签: javascript pass-by-reference

我认为对象是作为参考传递的。但是当我删除b时,它仍然存在于c中。请看这个例子:

第一部分对我有意义,因为它通过引用传递:

var a = {b: {val:true}};

a.c = a.b;
a.b.val = 'rawr';

console.log(uneval(a)); // outputs: "({b:{val:"rawr"}, c:{val:"rawr"}})"

现在这部分对我没有意义:

var a = {b: {val:true}};

a.c = a.b;
a.b.val = 'rawr';
delete a.b;

console.log(uneval(a)); // outputs: "({c:{val:"rawr"}})"

所以b属性被删除,但c属性将属性保存到删除前引用的属性。这是javascript中的错误吗?

编辑: 谢谢所有回复!所以它不是一个错误,这种行为实际上是非常好的,它允许人们改变"键" /"属性"保留对象时的名字! :)

6 个答案:

答案 0 :(得分:55)

......我迟到了?以下是我对它的解释(阅读其他答案,这只是为了用视觉表示来支持这些答案):

  1. 使用其他对象(a)初始化空对象value:true
  2. enter image description here

    1. 使用属性a指定空对象b,引用另一个对象(value:true)。
    2. enter image description here

      1. 为对象a指定属性c ,引用同一对象value:true)。
      2. enter image description here

        1. 删除 b,因此a.b不再引用到子对象(value:true)。< / LI>

          enter image description here

          1. 主要对象a的最终表示。
          2. enter image description here

            因此,我们可以通过直观表示轻松地看到子对象是如何被保留的:)

答案 1 :(得分:32)

不,这不是JavaScript中的错误。

您对a.c = a.b所做的是,您正在创建指向同一对象的另一个链接,这意味着a.ba.c都引用了同一个子对象{{1} }。

执行{val: "rawr"}时,您没有删除子对象,只是从delete a.b删除a.b属性。这意味着a仍会引用同一个对象。

如果你也要删除a.c属性,那么子对象将会消失。

答案 2 :(得分:6)

有两点需要注意,首先,正如其他答案所述,delete关键字仅删除您访问该属性的对象的属性。

要注意的第二件事是,JavaScript不会通过引用传递。它总是作为值传递,值有时是引用。

例如:

var a = {
   someObject: {}
};
var someObject = a.someObject;

someObject = 'Test';

console.log(a.someObject); // outputs {}

在通过引用传递的语言中,这可能会导致错误,因为它通常意味着强大的变量类型。

答案 3 :(得分:5)

那是因为:

  

删除操作符从对象中删除属性。   MDN Delete

b对应的条目 Object {val: true}已从a中删除。 c中的条目a仍然引用此对象。如果您尝试删除c.vala.b.val,您仍然可以看到效果级联到另一个。

您尝试做的事情,即解除分配数据并期望将其级联,并不会在javascript中发生。如果您有C ++背景,请考虑将所有javascript对象视为引用计数。我可以删除它的引用(即,指向该对象的条目),但我无法删除该对象本身。这是javascript引擎的纯粹特权。

答案 4 :(得分:5)

有了这一行,你认为c指向b:

a.c = a.b;

但实际上c和b都指向{val:true}对象,因此如果删除b,则对象仍然存在。 你可以简单地认为c和b都只是“标签”贴在{val:true} object

答案 5 :(得分:4)

不,这不是一个错误。

delete命令不会删除该属性引用的对象,它只删除该属性。如果该对象是从其他地方引用的(在这种情况下是另一个属性),则该对象仍然存活。

这就像你有两个指向同一个对象的变量一样,并改变一个变量的值:

var a = { val: true };
var b = a;
a = null;
console.log(b.val); // b still has a reference to the object