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.csdn.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了。我只是猜想。。。连等式可能并不会去计算过程,其中所有的值都直接被最后一个等号的值给赋值,其中,引用类型的赋值. 会优先赋值计算。
这个图表示最后的结果,并不能表示赋值过程。