搞懂JavaScript中的连续赋值

搞懂JavaScript中的连续赋值

前段时间老是被一道题刷屏,一个关于连续赋值的坑。 遂留下一个笔记,以后再碰到有人问这个题,直接丢过去链接。。

题目代码:

let a = { n: 1 }
let b = a

a.x = a = { n: 2 }

console.log(a.x) // => undefined
console.log(b.x) // => { n: 2 }

首先解释一下连续赋值的意思: 表达式variable = 1,这个为赋值语句。 当我们要给多个变量进行赋值时,有一个简单的写法。 variable1 = variable2 = 1,这个我们就称之为连续赋值。

再来说上边的那道题,我一次看到这个题的时候,答案也是错了,后来翻阅资料,结合着调试,也算是整明白了-.-

前两行的声明变量并赋值,使得ab都指向了同一个地址({ n: 1 }在内存中的位置)

为了理解连续赋值的运行原理,我们需要结合着ECMAScript的文档来解释一下=赋值的执行过程

图中出现了一个关键字LeftHandSideExpression(我们简称为LHS) MDN对该关键字的解释为“Left values are the destination of an assignment.”,翻译过来大概就是:LHS是用来分配赋值操作结果存放的位置(也就是=右边的这坨东西要放到哪)。

在执行一个赋值操作时,我们首先要取出=左侧的变量,用来确定这次赋值操作最终结果的存放位置。 然后运算=右侧的表达式来获取最终的结果,并将结果存放入对应的位置,也就是前边取出的变量所对应的位置。

再来说连续赋值,其实就是多次的赋值操作。

我们从代码的第一行开始,画图,一个图一个图的来说:

  1. let a = { n: 1 }声明了一个变量a,并且创建了一个Object{ n: 1 },并将该Object在内存中的地址赋值到变量a中,这时就能通过a来获取到{ n: 1}引用类型的值是只存放地址的,而不是直接存放原始值({} !== {}
  1. let b = a声明一个变量b,并且将a赋值给b,这时,ab都指向了{ n: 1 }
  1. 执行表达式(a.x = a = { n: 2 }),取出a.x的位置,由于a的值为{ n: 1 },所以取属性xundefined,遂在内存中开辟一块新的空间作为({ n: 1}).x的位置:
  1. 执行剩余表达式(a = { n: 2 }),取出a的位置,因为a是一个已声明的变量,所以该步骤并不会有什么改变;
  2. 执行剩余表达式({ n: 2 }),为{ n: 2 }在内存中开辟一块空间存放数据:
  1. { n: 2 }赋值到第4步取出的a对应的位置:
  1. { n: 2}赋值到第3步取出的a.x对应的位置:

这时我们就完成了整个赋值步骤:

  • 变量a指向{ n: 2 }
  • 变量b指向{ n: 1, x: { n: 2} }
  • 也就是说a === b.x

小记

该代码坑就在于:赋值运算会在运算=右侧前就取出了要赋值的位置,而不是获得结果后再去取出赋值位置的。 先取位置,后赋值 所以说,看文档很重要 很重要 很重要

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

最常见的 35 个 Python 面试题及答案(2018 版)

作为一个 Python 新手,你必须熟悉基础知识。在本文中我们将讨论一些 Python 面试的基础问题和高级问题以及答案,以帮助你完成面试。包括 Python ...

8073
来自专栏JavaEdge

青铜到王者 ,快速提升你 Go语言的段位! "狗"语言实战(二)- 基础语法1 变量定义

1424
来自专栏大闲人柴毛毛

String类中你不知道的知识

直接量创建对象更高效 在Java中,创建一个字符串有两种方法: //第一种方法 String str1 = "字符串1"; //第二种方法 String str...

2936
来自专栏Hongten

python开发_python中str.format()

2042
来自专栏aCloudDeveloper

C++中引用详解

引用简介   引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。   引用的声明方法:类型标识符 &引用名=目标变量名;   【...

1895
来自专栏java 成神之路

JAVA对象在JVM中内存分配

35712
来自专栏IT可乐

深入理解计算机系统(3.8)------数组分配和访问

  上一篇博客我们讲解了汇编语言中过程(函数)的调用实现。理解数据如何在调用者和被调用者之间传递,以及在被调用者当中局部变量内存的分配以及释放是最重要的。那么这...

22010
来自专栏老九学堂

稳准狠!最全讲解!初学者必看的C语言字符串知识

字符数组和普通数组一样,也是通过下标引用各个元素。 【示例】输出字符数组中的元素。

921
来自专栏从零开始学 Web 前端

01 - JavaSE之基础及面向对象

byte(-128 ~ 127) short(-32768 ~ 32767) int(-2147483648 ~ 2147483647)

1734
来自专栏marsggbo

C++学习笔记之模板篇

一、模板 不管是函数模板还是类模板,在未初始化前都是不占用内存的。 另外一般来说模板代码不能分开编译,即不能分开写成.h文件和.c文件,需要写成一个文件。 ...

2188

扫码关注云+社区

领取腾讯云代金券