请向我解释这一现象。
this.testObject = { a: 1, b: { a: 3, b: { a: 78, b: null } } };
let g = this.testObject;
while (g.b) {
g = g.b;
}
g.b = {
a: 79,
b: null
};
console.log(this.testObject); // { a: 1, b: { a: 3, b: { a: 78, b: { a: 79, b: null } } } }
现在我决定坚持使用this.testObject
并删除g
:
this.testObject = { a: 1, b: { a: 3, b: { a: 78, b: null } } };
while (this.testObject.b) {
this.testObject = this.testObject.b;
}
this.testObject.b = {
a: 79,
b: null
};
console.log(this.testObject); // {a": 78,b": {a": 79,b": null}
怎么回事?我对g
的赋值是如何以这种方式影响这个对象的?
在第一个片段中,若我执行了g=g.b
,那个么我基本上是在为g
分配一个新值。但若我明确地这样做,那个么结果就不一样了?
this.testObject = {a:1, b:{a:3,b:{a:78, b:null}}};
let g = this.testObject;
while(g.b){
g = {a:7777, b:null};
}
g.b={a:79, b:null};
this.testObject; // {a": 1,b": {a": 3,b": {a": 78,b": null}
我猜您希望这两个片段产生相同的结果。但代码并没有做同样的事情。
在第一个示例中,您使用g
作为某种参考。这意味着每次在while循环中设置g
时,都不会以任何方式影响this.testObject
,因为您只是";移动";引用。但它仍然是一个引用,因此更改g
引用的对象内部的任何内容,也将在this.testObject
中设置它,从而产生第一个示例中得到的结果。
在第二个示例中,每次在while循环中替换this.testObject
。因此设置this.testObject = this.testObject.b
将移除外部对象,导致this.testObject
从:
{ a: 1, b: { a: 3, b: { a: 78, b: null } } }
收件人:
{ a: 3, b: { a: 78, b: null } }
由于this.testObject.b
不为空,您将再次重复此操作,使this.testObject
变为:
{ a: 78, b: null }
最后,将this.testObject.b
设置为一个新对象,覆盖以前的null值。这将导致您在第二个示例中得到的输出。
通常在回答这些问题时,人们会在它们之间画方框和箭头来指示指针,但我很懒,所以让我们考虑一个简单的虚拟机。这台机器可以对存储块及其数字(又称"指针"(进行操作。有三种操作:
分配:分配一个内存块,用一些数据初始化它,并返回一个指向它的指针(表示为$number
(
就这台机器而言,您的第一个片段将翻译为:
// this.testObject = { a: 1, b: { a: 3, b: { a: 78, b: null } } };
allocate: $1 = {a: 78, b: null}
allocate: $2 = {a: 3, b: $1}
allocate: $3 = {a: 1, b: $2}
write: this.testObject = $3
// let g = this.testObject;
write: g = $3
// while (g.b) { g = g.b; }
write: g = $3.b // first pass, g is now $2
write: g = $2.b // second pass, g is now $1
// g.b = { a: 79, b: null }
allocate: $4 = { a: 79, b: null }
write: $1.b = $4
// console.log(this.testObject);
read: $3 ==> {a: 1, b: $2}
read: $2 ==> {a: 3, b: $1}
read: $1 ==> {a: 78, b: $4}
read: $4 ==> { a: 79, b: null }
基本上每个CCD_;分配";操作中,每个赋值都是"0";写";和CCD_;读取";。尝试";翻译";你的其他片段到这台机器,你会看到实际发生了什么。