前言
今天心血来潮,突然想起来最近很多人问的这道题目:
var a = { n:1};var b = a;a.x = a = { n:2};console.log(a.x); // --> undefinedconsole.log(b.x); // --> {n:2}复制代码
我一开始也看过去就是
console.log(a.x); // --> {n: 2}console.log(b.x); // --> undefined复制代码
回看赋值定义
ECMAScript定义
翻译成人话
1.计算表达式A,得到一个引用refA;2.计算表达式B,得到一个值valueB;3.将valueB赋给refA指向的名称绑定;4.返回valueB。复制代码
我们按照规范用脑子运行一下 我们运行一次,因为赋值运算具有右结合这个特性即:
赋值运算右结合特性
A1 = A2 = A3 = A4 => A1 = (A2 = (A3 = A4))
式子转换 a.x = a = {n:2}; = > a.x = (a = {n: 2})
实例解析
- 计算左侧的refA,此时右侧表达式还未运行,a的引用还没有改变和b指向同一个对象,为了方便我们把这个refA的值记为地址address1
- 计算右侧表达式(a = {n: 2}),此时a指向了新的对象,同时返回了这个表达式的结果,一个指向{n:2}对象的匿名引用,地址为address2
- 将2的计算结果值,匿名引用,赋值给1得到的ref,此时的ref仍然是改变前的address1,所以将address2的地址值赋给了address1的a变量,当然b此时的地址为address1,所以就会出现 图解
console.log(a.x); // --> undefinedconsole.log(b.x); // --> {n:2}复制代码
小结
其实这种题目看似难,实际上真的难(划掉),之前我也留意过这个问题,然后发现很多都是自圆其说,我不反对,相反,我觉得这些人很有想法,但是呢,我更愿意找更多的例子来证明我的想法,一般晦涩的场景,我回去翻一下ECMAScript规范,看规范怎么说,这里是,如果喜欢文章,可以给个小星星鼓励下喔,里面有很多我平时学习的思考,不过还未提炼过,不嫌弃可以随便看看。