JS 解惑 - 连等表达式

发布于 2023-10-03 18:32:17 字数 5164 浏览 38 评论 0

问题

如下 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 日

关于连等表达式多啰嗦一些

连等表达式执行过程说明

  1. 先解析连等表达式,进行变量提升(hoisting)
    • 如果是局部变量,不存在则先定义
  2. 将连等式最后一个值,同时赋给前面的其它变量;
    • 如果最后一个值是对象,则是将这个对象先在内存中开辟一个位置(匿名),然后将这个指针指向前面的所有变量。

关于以上第 1 步的详细解释

比如:

var str=str1=str2=123;

解析过程如下:

  1. 先找到表达式中的变量: strstr1str2
  2. 进行变量提升,并定义:
    • var str ,表示这是一个局部变量,则直接在当前执行函数中定义变量 str,默认值: undefined

注意: str1str2 ,由于他俩前面并没有直接有 var 符号,但是又得为它们赋值,这时候 JS 引擎赋值时,就会把他们挂到全局对象 window 对象上,因为 window 对象已经存在,所以不会在定义了;而对象的属性,只有在赋值时,才会动态在堆内存中追加。所以, var1var2 也不会创建。

记住:变量提升创建的,只包含:基本类型、对象和声明的函数,不包含对象上的属性。

接下来就是一步步赋值的过程了,见下面第 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);//?

大家先自己给出一个答案,然后看看下面的分析跟你想的一样不?

详细分析

第一步:先将代码中的变量提升,不存在的变量先定义。

  1. 先找出以上代码片段中的所有变量
    • a
    • b
  2. 定义变量
    • 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);//?

第二步:一步步执行代码片段并赋值。

  1. a = {n:1} 将 a 赋值为一个对象 {n:1} ,这里发生了什么事情?

  2. b = a 将 a 对象赋值给 b,我们知道,对象赋值其实就是指针的指向问题,就是 b 的指针也指向了 a 的值;

  3. a.x = a = {n:2} ,这一步我们按照上方的原理(并不是依次从右往左执行),把它拆解一下:

    • a.x = {n:2} ;
    • a = {n:2}
  4. 先看前一步, a.x = {n:2} ,其实就是在 a 的堆内存中,再额外增加一个属性 x,并且指向新的对象,如下:

    • 执行完这一步,大家能看到,其实这时候:a 和 b 还是指向同一个对象,只是那个对象多了一个属性 x 而已。
    • 这时候:a.x = b.x 都等于 {n:2}
  5. 再看后一步, 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 个地方:

  1. 很多人把连等当成从右往左一个变量给另一个变量赋值!其实不是;
  2. 最后 {n:2} 是个新的对象,注意的地方是对象赋值,一定是一个新的地址了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

半﹌身腐败

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文