Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.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_Javascript Objects - Fatal编程技术网

Javascript 为什么不是';当发生重新分配时,此对象是否复制为空?

Javascript 为什么不是';当发生重新分配时,此对象是否复制为空?,javascript,javascript-objects,Javascript,Javascript Objects,假设我创建一个对象,复制它(通过引用),然后使其无效: 让obj={ 道具:“一” } 让otherObj=obj console.log(otherObj==obj)//符合事实的 控制台日志(对象道具)//一 obj=null; 控制台日志(其他对象道具)//这不应该是未捕获的TypeError:无法读取null的属性“prop”?否,因为引用在您进行新赋值时丢失,所以其他obj仍将包含旧引用 换句话说,由于您修改了对象(例如,更改其某些字段),则otherObj和obj都将看到更新,但当

假设我创建一个对象,复制它(通过引用),然后使其无效:

让obj={
道具:“一”
}
让otherObj=obj
console.log(otherObj==obj)//符合事实的
控制台日志(对象道具)//一
obj=null;

控制台日志(其他对象道具)//这不应该是未捕获的TypeError:无法读取null的属性“prop”?
否,因为引用在您进行新赋值时丢失,所以其他obj仍将包含旧引用


换句话说,由于您修改了对象(例如,更改其某些字段),则
otherObj
obj
都将看到更新,但当您重新分配其中一个时,您会破坏绑定,并且每个对象都将引用内存中的不同位置。

您必须区分对象和对该对象的引用。变量
obj
otherObj
只保留对t的引用对象,内存中指向该对象的指针。它们不是对象的副本,也不是同一对象。。它们指向同一对象

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

let obj = {
    prop: 'one'
}
您正在创建一个新引用,如下所示:

obj
只指向对象所在的内存点,称为引用。接下来,您可以:

let otherObj = obj
这相当于:

在这里,您将
obj
的引用分配给
otherObj
。它们现在都引用内存中的同一对象,尽管它们彼此完全独立。
otherObj
obj
的引用,因此它们都引用相同的对象,但是分开的。根据链接:

在这种情况下,将创建一个新对象B,并将a的字段值复制到B

[……]

如果字段值是对对象的引用(例如,内存地址)它复制引用,因此引用与对象相同的对象

最后,您可以这样做:

obj = null
这是这样的:


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

否,要理解您为什么需要理解“引用”的概念

在您的示例中,这段代码“创建”了您的对象:

let obj = {
    prop: 'one'
}
在这种情况下,“obj”不是对象本身(像内存位置),而是一个对象“引用”-基本上它是指向指针的指针

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

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

这是一个非常重要的概念——如果将变量传递给函数,则该参数是对对象的“引用”(字符串和数字等基本上不可变的东西除外)。您可以在函数外部重新分配变量,参数将保持不变

另外,在另一面,当两个引用都指向同一对象时,对成员的更改将通过两个引用反映出来。如果你想要两个不同的副本,你必须做像“克隆”一个对象这样的事情——而不仅仅是引用它


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

您应该区分深度副本和浅层副本。你所做的叫做浅拷贝。以下是可视化:

浅拷贝

深度复制

对于浅拷贝,两个对象(
obj
otherObj
)引用相同的内存位置。这就是为什么更改一个对象的值时,另一个对象也会更新

同时,对于深度副本,每个对象都有自己的内存位置。更改一个对象的值时,它不会影响另一个对象


您可以从中了解更多信息。

否,因为变量在JavaScript中是非类型化的。这意味着JavaScript引擎可以根据包含的信息确定变量的类型。在Visual Basic中,一种非常类似的变量称为

所以如果你说

let otherObj = obj;
如果
obj
是一个对象值,那么现在有两个变量知道它们是对象,并且具有相同的对象值(不必讨论如何将对象实现为引用)

所以如果你现在执行

obj = null;
obj
的值被值
null
覆盖(顺便说一句,它有一个数据类型“null”,它只支持一个值:null

显然,给一个变量赋值并不能改变另一个变量的值。编程语言依赖于此


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

不,您只是更改var指向的对象,而不是目标本身。如果修改了对象,两个变量都会反映这一点。将第二个var视为别名;您删除的是昵称,而不是人。