微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么不将对象分配给变量时,我的 JS 对象会错误地更改?

如何解决为什么不将对象分配给变量时,我的 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: 79,b: null } } } }

现在我决定坚持使用this.testObject删除g

this.testObject = { a: 1,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: null } }

并且由于 this.testObject.b 不为空,因此您再次重复此操作,使 this.testObject 变为:

{ a: 78,b: null }

最后,您将 this.testObject.b 设置为一个新对象,覆盖之前的空值。这将导致您在第二个示例中获得的输出。

,

通常在回答这些问题时,人们会在它们之间画框和箭头来表示指针,但我很懒,所以让我们考虑一个简单的虚拟机。这台机器可以对内存块及其编号(又名“指针”)进行操作。共有三种操作:

  • allocate:分配一个内存块,用一些数据初始化它并返回一个指向它的指针(表示为$number
  • write:将变量或属性的值设置为指针,使变量“指向”对应的内存块
  • read:给定一个指针,返回其内存块的内容

就这台机器而言,您的第一个片段将转换为:

// this.testObject = { a: 1,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 }

基本上,每个 {...} 是一个“分配”操作,每个分配是一个“写”,而 console.logs 是“读”。尝试将您的其他片段“翻译”到这台机器上,您就会看到实际发生了什么。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。