js对象等号赋值的bug

时间:2023-03-09 13:44:04
js对象等号赋值的bug
var a = {n: 1};
var b = a;
a.x = a = {n: 2}; console.log(a.x);
console.log(b.x);
有道题是这样的,觉得很奇葩,分析一下

1.对象 引用类型

对象属于引用类型,c,java,js里面都是的,对象就是引用类型,包括数组。

上面的a是引用类型,a保存的是对象 {n: 1}的地址,对这个对象的引用。b = a 。把a里面的地址赋值给了b,b也指向{n: 1}这个对象的物理地址。所以,a 一旦做赋值更改,修改的是a对引用的修改。b也同时修改,b修改的时候,a也会被修改。这就是引用类型。

堆和栈。堆是真实的{n:1} 。栈里面存放的是堆的物理地址,值比较小。根据栈的地址去找堆里面的数据。

2.

var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a===b.x); //true

  第二个奇葩结果

3.

https://blog.****.net/qiphon3650/article/details/78860973

我把这篇看了,然后觉得还是不理解

就这句: 执行a.x=a,此时a已经指向了新对象,而a.x因为在执行前保留了原引用。

不理解的点是 a都已经改变指向了,a指向了{n: 2},a.x里面的a的指向当然也改变成了{n: 2},为什么,a.x还会保留原引用

4.我又看了别人写的,觉得这样比较好绕回来

a.x的运算优先级最高

也就是说

var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a===b.x); //true

这段代码可以写成这样

var a = {n:1};
var b = a;
a.x = (a = {n:2});
console.log(a===b.x); //true

  

这样就解释通了

1.a指向 {n: 1};   ---> var a = {n: 1};

2.b指向 a指向的这个 {n: 1}  ---> var b = a;

  3.计算 a.x = (a = {n: 2});    a.x的值是 后面值的结果,后面的值先不管。此时 a.x = (某个值),是先计算的。a.x 这个a 指向并没有被         改变

  所以. a.x 里面的a仍然是原来的 {n: 1};a.x里面的值是后面( a = {n: 2})这个结果的返回值。这个返回值是 {n: 2};

4.所以拆分成a.x = { n: 2 }; 然后原来的a的值被 a = {n: 2},b是对原来对象的引用; a 最后赋值的结果是a = {n: 2};

所以。a.x是underfined,因为新的a里面并没有 x这个属性

所以我觉得这个赋值运算的结果,a = {n: 2}这个a并没有更改引用的时候,它的返回值就已经确定了,就先赋值给原来的a.x里面的a了。我只是猜想。。。连等式可能并不会去计算过程,其中所有的值都直接被最后一个等号的值给赋值,其中,引用类型的赋值. 会优先赋值计算。

这个图表示最后的结果,并不能表示赋值过程。

js对象等号赋值的bug