JavaScript数组解构简写赋值出现undefined及TypeError是什么原因?
问题根源
你的代码问题完全是JavaScript自动分号插入(ASI)规则的经典坑,和引用地址没有任何关系。
具体解析过程
JavaScript默认不会在以[开头的行前自动补充分号,所以会把下面两行代码当成同一句解析:
// 你写的代码(上一行末尾没有分号) var [newY, newZ] = [y, z] [y, z] = [oriY, oriZ] // JS实际解析的代码 var [newY, newZ] = [y, z][y, z] = [oriY, oriZ]
连续赋值是从右往左执行的,我们拆解执行逻辑:
- 方括号内的
y, z会被识别为逗号运算符,最终取最后一个值z作为索引值,等价于访问临时数组[y, z]的索引z - 把右值
[oriY, oriZ]赋值给这个临时数组的对应索引位置,整个赋值表达式的返回值就是右值本身 - 再把这个返回值解构赋值给
newY和newZ,所以你返回的[newY, newZ]其实就是[oriY, oriZ]的值,和之前的计算结果完全无关,你写的恢复全局变量的逻辑也根本没有生效。
两次输出不一致的原因
- 第一次调用bar:全局变量
y、z是var声明的默认值undefined,所以oriY、oriZ都是undefined,最终newY、newZ被赋值为undefined,返回[undefined, undefined]。同时这里的赋值操作是作用在临时数组上,没有修改全局y、z,第一次调用结束后全局y=8、z=40。 - 第二次调用bar:全局变量
y、z已经是8、40,所以oriY=8、oriZ=40,最终newY、newZ被赋值为8、40,正好和你预期的结果巧合一致。
你遇到的TypeError: Cannot set property '40' of undefined报错,是当你打开console.log(oriY, oriZ)的注释后,代码又会被合并解析为:
console.log(oriY, oriZ)[y, z] = [oriY, oriZ]
console.log的返回值是undefined,相当于给undefined的40属性赋值,自然就抛出类型错误。
修复方法
只需要补充分号即可,两种方案任选:
- 在上一行末尾加分号
var [newY, newZ] = [y, z]; [y, z] = [oriY, oriZ]
- 在解构赋值行的开头加分号(更稳妥的规避ASI坑的写法)
var [newY, newZ] = [y, z] ;[y, z] = [oriY, oriZ]
内容的提问来源于stack exchange,提问作者Phan Trong Hieu
相关产品推荐
相关产品推荐

