JavaScript连续赋值的执行顺序问题

本文深入探讨了JavaScript中连续赋值的执行顺序和原理,通过具体示例解释了为何连续赋值与顺序无关,以及引用类型赋值时的内存指向问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引子

一道阿里的面试题

let a = {
  n:2
}
let b = a
a.x = a = {
  l:2
}
// 说出 a 和 b的输出值

我第一次看到这个题目是懵逼的,因为平时没注意=的多次赋值的执行顺序的问题。
第一种答案:

a => {
	l:2,
	x:{
		l:2
	}
}
b=> {
	n : 2
}

第二种答案:

a => {
	l:2
}
b=> {
	n : 2,
	x:{
		l:2
	}
}

答案:第二种

分析

=是不论前面有多长,最终的取值都取决于最末的赋值,有点不太好理解,我们做几个编译试试就明白了。
就拿上面的例子看看,我们调换赋值的顺序得到的结果是一样

let a = {
  n:2
}
let b = a
a = a.x = {
  l:2
}

输出的值为:

a => {
	l:2
}
b=> {
	n : 2,
	x:{
		l:2
	}
}

我们修改下a的值来看下,b.x是否与a是否应用同一个对象

let a = {
  n:2
}
let b = a
a.x  = a = {
  l:2
}
a.l = 3
console.log(a,b)

输出:

a => {
	l:3
}
b=> {
	n : 2,
	x:{
		l:3
	}
}

很明显引用的对象是同一个,并不是声明了2个对象进行赋值
在这里插入图片描述

结论

  • 多次赋值与顺序无关,是同时进行赋值的
  • 每个节点的变量最终赋值的值取决去最后一个等号的右边值
  • 如果赋值是引用类型,则最终指向的是同一个对象
思考

其实我们直接使用变量名字的时候,其实使用的是这个变量名的地址。
当执行到连续赋值a.x=a={n:1}这个语句的时候,这里的代码环境会进行解析,看起来只是单纯地涉及了一个变量a
在环境中,已经存在了一个a,我们知道第一次使用var会进行声明提升,而如果没有使用过var的话,这个变量就会变成全局变量。
我们回到原题上,.这个是进行对象访问,你也可以通过a["x"]来进行访问,因为我们可以直接使用.来进行直接赋值,所以这个.自身带有赋值声明的功能,如何体现呢?
我们试想下,如果直接返回一个没有申明过的变量会怎么样呢?
会直接报错,不可以引用未声明过的变量。
而仅仅是声明变量没有赋值,我们进行输出会返回undefined
如果我们通过使用.来引用一个没有声明过的属性,它却会返回undefinded这个属性,这样非常明显地说明了通过.是会进行声明变量的功能


这就可以解释为什么a.xa这2个a为什么会不相等
因为a.x引用的是堆内存的里面的属性变量,在解析的时会直接对这个地址的变量进行操作,而a时访问变量栈内存里面这个变量名,所以进行赋值操作并不会影响前者,因为解析这个语句时一次性全部读取再进行赋值,而不是进行分段读取赋值的。

·所以就解释了与顺序无关,所有的属性都将会被赋值到最右的值·

这里涉及了作用域链、VO/AO等一些原理,希望大家如果想要深入学习前端的话,建议学习下这些概念,对分析JS执行非常有帮助。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值