我认为对象是作为参考传递的。但是当我删除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中的错误吗?
编辑: 谢谢所有回复!所以它不是一个错误,这种行为实际上是非常好的,它允许人们改变"键" /"属性"保留对象时的名字! :)
答案 0 :(得分:55)
......我迟到了?以下是我对它的解释(阅读其他答案,这只是为了用视觉表示来支持这些答案):
a
)初始化空对象value:true
。
a
指定空对象b
,引用另一个对象(value:true
)。
a
指定属性c
,引用同一对象(value:true
)。
b
,因此a.b
不再将引用到子对象(value:true
)。< / LI>
醇>
a
的最终表示。
因此,我们可以通过直观表示轻松地看到子对象是如何被保留的:)
答案 1 :(得分:32)
不,这不是JavaScript中的错误。
您对a.c = a.b
所做的是,您正在创建指向同一对象的另一个链接,这意味着a.b
和a.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.val
或a.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