JavaScript连等于号A=B=C的运算方法

阅读() @2019-05-12 11:46:36

今天看到一道非常有意思的面试题,值得思考,因为它结合了变量赋值与运算符的知识点,代码如下:

var foo = {n:1};
var bar = foo;
foo.x = foo = {n:2};
console.log(foo.x);//undefined
console.log(bar.x);//Object { n: 2 }

分析如下:

假设有一句代码: A=B=C; ,赋值语句的执行顺序是从右至左,所以问题在于:

是猜想1: B = C; A = C;

还是猜想2: B = C; A = B;

我们都知道若两个对象同时指向一个对象,那么对这个对象的修改是同步的,如:

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

所以,连等赋值真正的运算规则是:B = C; A = B。

连续赋值是从右至左永远只取等号右边的表达式结果赋值到等号左侧

通过上面可以看到连续赋值的真正规则,那么再回归到文章开头的那个案例,如果按照上述规则将连续赋值拆开会发现结果不一样了,如:

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

所以连续赋值语句虽然是遵从从右至左依次赋值的规则。

所以我认为本文最上边那段代码的逻辑是:

1、JS代码从上到下执行,执行之前先定义foo和bar;

2、在内存中创建一个新对象{n: 1};

3、执行foo={n: 1};

4、将foo的引用地址赋给bar;

5、将foo的引用地址从指向{n: 1}改为指向新的{n: 2};

6、执行foo.x=foo,此时a已经指向了新对象,而foo.x的foo依然指向原先的{n:1}对象,所以给原对象新增一个属性x,内容为{n:2}也就是现在foo;

7、语句执行结束,原对象由{n:1}变成{n:1,x:{n:2}},而原对象因为无人再引用他,所以被GC回收,当前foo指向新对象{n:2};

8、所以就有了文章开头的运行结果,再执行foo.x,自然就是undefined了;

9、因为bar引用的原来{n: 1}的内存地址,由于foox.x的改变,所以也在原来基础上新增了x: {n: 2}的对象。

图解如下:

javascript连等于号的图解

相关推荐:

JavaScript中传值与传址的概念解析

关于javascript执行顺序、变量提升、作用域的问题

微信二维码