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

Noi*_*art 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"}})"
Run Code Online (Sandbox Code Playgroud)

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

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

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

console.log(uneval(a)); // outputs: "({c:{val:"rawr"}})"
Run Code Online (Sandbox Code Playgroud)

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

编辑:谢谢所有的回复!所以它不是一个bug,而且这种行为实际上非常好,它允许人们在保留对象的同时更改"key"/"property"名称!:)

use*_*110 55

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

  1. a用另一个对象初始化空对象(value:true).

在此输入图像描述

  1. a使用b引用另一个对象的属性(value:true)分配空对象.

在此输入图像描述

  1. a使用c 引用同一对象的属性(value:true)分配对象.

在此输入图像描述

  1. 删除 b,因此a.b不再引用子对象(value:true).

在此输入图像描述

  1. 主要对象的最终表示a.

在此输入图像描述

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

  • 这很棒.我喜欢视觉表现. (8认同)
  • 稍后我们将完整的垃圾收集过程描述为少量图片!(只需在云上写GC-Magic并让对象消失) (2认同)

Fro*_*ost 32

不,这不是JavaScript中的错误.

你有什么用做的a.c = a.b是,你在另外一台链接到同一个对象,这意味着既a.ba.c被引用相同的子对象{val: "rawr"}.

执行此操作时delete a.b,您不是要删除子对象,而只是a.b从中删除属性a.这意味着a.c仍然会引用同一个对象.

如果您也要删除该a.c属性,则子对象将消失.

  • 谢谢你解释Frost!我的下一个问题是如何删除该子对象,你也回答了这个问题,如果没有任何东西持有对该对象的引用(通过删除`ac`)那么它就完全消失了.非常感谢!这种行为实际上非常好,它允许人们在保留对象的同时更改"键"/"属性"名称!:) (3认同)

axe*_*uch 6

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

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

例如:

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

someObject = 'Test';

console.log(a.someObject); // outputs {}
Run Code Online (Sandbox Code Playgroud)

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


Sha*_*adh 5

那是因为:

delete运算符从对象中删除属性. MDN删除

与之 b对应的条目Object {val: true}将从中删除a.该条目ca还指该对象.如果您尝试删除c.vala.b.val,您仍然可以看到效果级联到另一个.

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


yel*_*ver 5

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

a.c = a.b;
Run Code Online (Sandbox Code Playgroud)

但实际上c和b都指向{val:true}对象,所以如果删除b,对象仍然存在.你可以简单地认为c和b都只是"标签"粘在{val:true}对象上