搞懂JavaScript中的连续赋值
时间:2022-05-10
本文章向大家介绍搞懂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
,这个我们就称之为连续赋值。
再来说上边的那道题,我一次看到这个题的时候,答案也是错了,后来翻阅资料,结合着调试,也算是整明白了-.-
前两行的声明变量并赋值,使得a
和b
都指向了同一个地址({ n: 1 }
在内存中的位置)
为了理解连续赋值的运行原理,我们需要结合着ECMAScript的文档来解释一下=
赋值的执行过程
图中出现了一个关键字LeftHandSideExpression(我们简称为LHS
)
MDN对该关键字的解释为“Left values are the destination of an assignment.”
,翻译过来大概就是:LHS
是用来分配赋值操作结果存放的位置(也就是=
右边的这坨东西要放到哪)。
在执行一个赋值操作时,我们首先要取出=
左侧的变量,用来确定这次赋值操作最终结果的存放位置。
然后运算=
右侧的表达式来获取最终的结果,并将结果存放入对应的位置,也就是前边取出的变量所对应的位置。
再来说连续赋值,其实就是多次的赋值操作。
我们从代码的第一行开始,画图,一个图一个图的来说:
-
let a = { n: 1 }
声明了一个变量a
,并且创建了一个Object
:{ n: 1 }
,并将该Object
在内存中的地址赋值到变量a
中,这时就能通过a
来获取到{ n: 1}
:引用类型的值是只存放地址的,而不是直接存放原始值({} !== {}
)
-
let b = a
声明一个变量b
,并且将a
赋值给b
,这时,a
和b
都指向了{ n: 1 }
:
- 执行表达式(
a.x = a = { n: 2 }
),取出a.x
的位置,由于a
的值为{ n: 1 }
,所以取属性x
为undefined
,遂在内存中开辟一块新的空间作为({ n: 1}).x
的位置:
- 执行剩余表达式(
a = { n: 2 }
),取出a
的位置,因为a
是一个已声明的变量,所以该步骤并不会有什么改变; - 执行剩余表达式(
{ n: 2 }
),为{ n: 2 }
在内存中开辟一块空间存放数据:
- 将
{ n: 2 }
赋值到第4
步取出的a
对应的位置:
- 将
{ n: 2}
赋值到第3
步取出的a.x
对应的位置:
这时我们就完成了整个赋值步骤:
- 变量
a
指向{ n: 2 }
- 变量
b
指向{ n: 1, x: { n: 2} }
- 也就是说
a === b.x
小记
该代码坑就在于:赋值运算会在运算=
右侧前就取出了要赋值的位置,而不是获得结果后再去取出赋值位置的。
先取位置,后赋值
所以说,看文档很重要 很重要 很重要
参考资料
- 同样的sql执行结果不同的原因分析 (r4笔记第27天)
- 情感分析的新方法,使用word2vec对微博文本进行情感分析和分类
- 垂直属性
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)
- 13(02)总结StringBuffer,StringBuilder,数组高级,Arrays,Integer,Character
- Mybatis-Generator生成Mapper文件中<if test="criteria.valid">的问题解答
- Java开源博客My-Blog之mysql容器重复初始化的严重bug修复过程
- 负margin的原理以及应用
- 关于exp/imp的总结学习(r4笔记第26天)
- 除了写烂的手写数据分类,你会不会做自定义图像数据集的识别?!
- shell脚本中字符串的常见操作及"command not found"报错处理(附源码)
- 绝对定位下的盒模型
- 运行shell脚本时报错"[[ : not found"解决方法
- 关于表联结方法(二) (r4笔记第23天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法