JS 解惑 - 连等表达式
问题
如下 3 个表达式的区别:
//sample1 var str = 123; var str1 = 123; var str2 = 123; //sample2 var str = 123,str1 = 123,str2 = 123; //sample3 var str = str1 = str2 = 123;
答案
//`sample1` = `sample2`,区别仅仅是代码风格而已; //sample2 var str = 123,str1 = 123,str2 = 123; //str,str1,str2 全部为局部变量 //sample3 var str = str1 = str2 = 123; //str 局部变量,str1,str2 为全局变量
最新补充于:2018 年 3 月 18 日
关于连等表达式多啰嗦一些
连等表达式执行过程说明
- 先解析连等表达式,进行变量提升(hoisting)
- 如果是局部变量,不存在则先定义
- 将连等式最后一个值,同时赋给前面的其它变量;
- 如果最后一个值是对象,则是将这个对象先在内存中开辟一个位置(匿名),然后将这个指针指向前面的所有变量。
关于以上第 1 步的详细解释
比如:
var str=str1=str2=123;
解析过程如下:
- 先找到表达式中的变量:
str
、str1
、str2
; - 进行变量提升,并定义:
var str
,表示这是一个局部变量,则直接在当前执行函数中定义变量 str,默认值:undefined
;
注意: str1
和 str2
,由于他俩前面并没有直接有 var
符号,但是又得为它们赋值,这时候 JS 引擎赋值时,就会把他们挂到全局对象 window
对象上,因为 window
对象已经存在,所以不会在定义了;而对象的属性,只有在赋值时,才会动态在堆内存中追加。所以, var1
和 var2
也不会创建。
记住:变量提升创建的,只包含:基本类型、对象和声明的函数,不包含对象上的属性。
接下来就是一步步赋值的过程了,见下面第 2 步的解释。
关于以上第 2 步的详细解释
比如:
var str=str1=str2=123;
并不是: 将 123 先赋值给 str2,再将 str2 赋值给 str1,再将 str1 赋值给 str;
而是: 将 123 赋值给 str2,再将 123 赋值给 str1,再将 123 赋值给 str;
也就是上方的连等式可以理解为:
var str; str = 123; str1 = 123; str2 = 123;
复杂示例
请大家给出如下表达式的执行结果:
var a = {n:1}; var b = a; a.x = a = {n:2}; console.log('a.x=',a.x);//? console.log('b.x=',b.x);//?
大家先自己给出一个答案,然后看看下面的分析跟你想的一样不?
详细分析
第一步:先将代码中的变量提升,不存在的变量先定义。
- 先找出以上代码片段中的所有变量
- a
- b
- 定义变量
var a
:定义局部变量 a,默认值undefined
;var b
:定义局部变量 b,默认值undefined
;
于是代码片段变为:
//第一步做的事情 var a; var b; //第二步开始的地方 a = {n:1}; b = a; a.x = a = {n:2}; console.log('a.x=',a.x);//? console.log('b.x=',b.x);//?
第二步:一步步执行代码片段并赋值。
a = {n:1}
将 a 赋值为一个对象{n:1}
,这里发生了什么事情?b = a
将 a 对象赋值给 b,我们知道,对象赋值其实就是指针的指向问题,就是 b 的指针也指向了 a 的值;a.x = a = {n:2}
,这一步我们按照上方的原理(并不是依次从右往左执行),把它拆解一下:a.x = {n:2}
;a = {n:2}
先看前一步,
a.x = {n:2}
,其实就是在 a 的堆内存中,再额外增加一个属性 x,并且指向新的对象,如下:- 执行完这一步,大家能看到,其实这时候:a 和 b 还是指向同一个对象,只是那个对象多了一个属性 x 而已。
- 这时候:a.x = b.x 都等于 {n:2}
再看后一步,
a = {n:2}
,就是将 a 的指针变化了,指向这个新的对象,如下:- 这时候:a = b.x 都等于 {n:2}(看蓝色的箭头指向同一个)
- 而这时候 a 指针对应的对象中
{n:2}
,根本不存在 x 这个属性,所以a.x=undefined
;
最终答案
console.log('a.x=',a.x);//undefined console.log('b.x=',b.x);//{n:2}
其实本题最容易绕晕的 2 个地方:
- 很多人把连等当成从右往左一个变量给另一个变量赋值!其实不是;
- 最后
{n:2}
是个新的对象,注意的地方是对象赋值,一定是一个新的地址了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论