为什么我的JS对象在没有将对象分配给变量时会错误地更改



请向我解释这一现象。

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(
  • write:将变量或属性的值设置为指针,使变量"点";到相应的存储块
  • 读取:给定一个指针,返回其内存块的内容
  • 就这台机器而言,您的第一个片段将翻译为:

    // 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_;读取";。尝试";翻译";你的其他片段到这台机器,你会看到实际发生了什么。

    相关内容

    • 没有找到相关文章

    最新更新