Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/452.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 通过引用复制到第二个属性的对象是否在删除原始属性后仍然存在?_Javascript_Pass By Reference - Fatal编程技术网

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

Javascript 通过引用复制到第二个属性的对象是否在删除原始属性后仍然存在?,javascript,pass-by-reference,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
时,它仍然存在于
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中的错误吗

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

不,这不是JavaScript中的错误

使用
a.c=a.b
所做的是创建指向同一对象的另一个链接,这意味着
a.b
a.c
都引用同一子对象
{val:“rawr”}

当您执行
删除a.b
操作时,您不是在删除子对象,而是在从
a
中删除
a.b
属性。这意味着
a.c
仍将引用同一对象

如果同时删除
a.c
属性,则子对象将消失。

不,这不是错误

delete
命令不会删除属性所引用的对象,它只删除属性。如果该对象是从其他地方引用的(本例中为其他属性),则该对象仍处于活动状态

这与将两个变量指向同一对象并更改一个变量的值相同:

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

“删除”操作符从对象中删除属性。

对象{val:true}
对应的条目
b
将从
a
中删除。
a
中的条目
c
仍然指向此对象。如果尝试删除
c.val
a.b.val
,仍然可以看到效果层叠到另一个


您试图做的事情,即释放数据并期望它被级联,在javascript中不会发生。如果你有C++背景,考虑把所有JavaScript对象当作引用来计算。我可以删除对它的引用(即“指向”这个对象的条目),但我不能删除对象本身。这是javascript引擎的纯特权。

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

a.c = a.b;
但实际上,c和b都指向{val:true}对象,因此如果删除b,对象将保留。
您可以简单地认为c和b都只是粘贴在{val:true}对象上的“标签”

有两件事需要注意,首先,正如在其他答案中所说的,delete关键字仅为您访问属性的对象删除属性

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

例如:

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

someObject = 'Test';

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

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

…我迟到了?以下是我对这一点的解释(也请阅读其他答案,这只是为了用视觉表现来支持这些答案):

  • 使用另一个对象初始化空对象
    a
    值:true
  • 为空对象
    a
    分配一个属性
    b
    ,该属性引用另一个对象(
    值:true
  • 为对象
    a
    分配一个属性
    c
    ,该属性引用同一对象(
    值:true
  • 删除
    b
    ,因此
    a.b
    不再引用子对象(
    值:true
  • 主对象的最终表示形式
    a

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

    感谢您的解释!我的下一个问题是如何删除该子对象,您也回答了这个问题,如果没有任何对象包含对该对象的引用(通过删除
    a.c
    ),那么它就完全消失了。非常感谢!这种行为实际上非常好,它允许人们在保留对象的同时更改“键”/“属性”名称!)感谢Guffa为您提供了另一个例子来解释这一点,我真的很感激!感谢Sharadh,这是一个非常有趣的观点:如何从a中删除val属性在b中也是一样的。当然,随时都可以。这和你的例子一样。就像将对象中的键
    val
    的值更改为
    rawr
    ,这里我们将从对象本身删除键。谢谢yelliver!你用的不同的词确实加强了别人的话。我非常感谢这些多重解决方案!感谢您对
    传递值的更正,这将对我有很大帮助。这是你提出的一个非常好的观点,我认为这是理所当然的,因为我没有考虑它。非常感谢您的澄清。这太好了。我喜欢视觉表现。这真是太棒了。谢谢你的视觉解释!你能把我们删除b和c的道具时会发生什么添加到视频中吗。子对象应该消失不?@Noitidart是的,它会消失。我会在以后有时间的时候再加上解释。再过几次编辑,我们就用小图片描述了整个垃圾收集过程!(只需在云上编写GC Magic并让对象消失)当我试图以图形方式演示GC时,我通常会选择一些类似于pacman的东西。谢谢!我会重新命名的。如果您使用的是调试器,最好只使用
    console.log(a)
    而不是
    console.log(uneval(a))
    ,因为它将显示属性和其他有用的调试器