2017-03-25 46 views
1

说我做一个对象,将其复制(如附图),然后废掉它:为什么重新分配时不会将此对象复制为空?

let obj = { 
 
    prop: 'one' 
 
} 
 

 
let otherObj = obj 
 

 
console.log(otherObj === obj); //true 
 

 
console.log(obj.prop); //one 
 

 
obj = null; 
 

 
console.log(otherObj.prop); //shouldn't this be Uncaught TypeError: Cannot read property 'prop' of null"?

不宜otherObj也为空,因为它们是同一个对象?

+1

不,你只是改变var指向的内容,而不是目标本身。如果你修改了这个对象,两个变量都会反映出来。把第二个var作为别名;你删除了昵称,而不是该人。 – dandavis

回答

1

您必须将对象和参考区分为该对象。变量objotherObj只是持有对象的引用,该对象是指向内存的指针。 它们不是对象的副本,它们不是同一个对象。他们指向为同一个对象。

为了更清楚地说明这一点,我将逐行解释。当你这样做:

let obj = { 
    prop: 'one' 
} 

你正在创建一个新的参考,像这样:

enter image description here

obj只是指向对象所在的内存斑点,称为引用。接下来,你这样做:

let otherObj = obj 

即相当于此:

enter image description here

在这里,您分配obj引用otherObj。他们现在都在内存中引用同一个对象,尽管它们完全相互独立。 otherObjobj的参考文献的shallow copy,所以它们都指的是相同的对象,但是是分开的。每链路:

在这种情况下新的对象B被创建,并且A的字段值被复制到B.

[...]

如果字段值是对一个对象的引用(例如,,内存地址)它复制引用,因此指的是同一对象作为不

最后你这样做:

obj = null 

这是这样的:

enter image description here

obj到内存中的对象的引用基本上被切断,现在obj p打到null,或什么也没有。由于objotherObj彼此独立,所以otherObj没有任何反应,它仍然指向内存中的对象。 objotherObj本身是独立的引用,但引用同一个对象。当您在内存中修改对象时,它会反映在两个引用上,但是当您通过中断对内存位置的引用来修改引用时,另一个事件不会发生任何变化。

0

不,因为参考在您完成新任务obj = null的确切时刻丢失,其他对象仍将包含旧的参考。

换句话说,因为你修改的对象(例如,改变它的一些字段),都otherObjobj将会看到更新,但是当你重新分配你打破债券其中之一,每一个都会参考到记忆中的不同位置。

0

不,理解为什么你需要理解“参考”的概念。

在您的例子的代码此位“创建”您的对象:

let obj = { 
    prop: 'one' 
} 

在这种情况下,“OBJ”是不是对象本身(如存储器位置),但是对象“参照” - 基本上它是一个指针指针。

将“obj”设置为null之前,还将“otherObj”指定为对SAME对象的引用。此时您有2个参考。

当您将“obj”设置为null时,该对象仍然存在,并仍被“otherObj”引用。它将被保存在内存中,至少直到它不再被“otherObj”引用。如果您将两个引用都设置为null,那么您将不再能够访问该对象本身,并且可能使其可以被Javscript引擎释放。

这是一个非常重要的概念 - 如果你将一个变量传递给一个函数,那个参数就是对象的“引用”(除了字符串和数字之类的东西,它们本质上是不可变的)。您可以在函数外重新分配变量,参数将保持不变。

另外,在flipside上 - 虽然两个引用指向相同的对象对成员的更改都反映了两个引用。如果你想要两个不同的副本,你必须做一些事情,比如“克隆”一个对象 - 而不仅仅是引用它。

理解引用对于管理Javascript中的闭包至关重要。

0

您应该区分深层副本和浅层副本。你在做什么叫做浅拷贝。下面是可视化:

浅拷贝

enter image description here enter image description here enter image description here

深层复制

enter image description here enter image description here enter image description here

对于浅拷贝,您的两个对象(objotherObj)都指向相同的内存位置。这就是为什么当你改变一个对象的值时,另一个对象也会被更新。

同时,对于深度复制,每个对象都有自己的内存位置。当你改变一个对象的值时,它不会影响另一个对象的值。

您可以从这个post了解更多。

-1

不,因为变量在JavaScript中是无类型的。这意味着JavaScript引擎可以根据它所包含的信息来确定变量的类型。在Visual Basic中,一个非常类似的变量称为"variant"

所以,如果你说

let otherObj = obj; 

其中obj是一个对象的值,你现在有两个变量,知道它们是对象,并具有相同的对象值(不进入对象是如何作为参考实现)。

所以,如果你现在执行

obj = null; 

obj值超过编写与价值null(顺带有一个数据类型为“空”,只支持一个值:)。

很明显,将一个新值赋给一个变量不应该改变另一个变量的值。编程语言依赖于此。

因此在obj的值已更新后,otherObj包含与之前相同的对象值:属性为“prop”,值为“1”的对象。

相关问题