JavaScript解构赋值交换变量遇报错:ReferenceError无法提前访问'b'
为什么解构交换变量会抛出"Cannot access 'b' before initialization"错误?
嘿,这个坑我踩过!问题根源其实是JavaScript的**自动分号插入(ASI)**在搞怪,咱们一步步拆解来看:
首先看你写的代码:
let a = 1 let b = 2 [b, a] = [a, b] console.log([a, b])
你以为这是三行独立的代码,但JavaScript的解析器不这么认为——当一行代码以[开头时,ASI不会自动在上一行末尾加分号,它会把这行和上一行合并成一个表达式,最终解析成这样:
let a = 1 let b = 2[b, a] = [a, b] console.log([a, b])
这里的2[b, a]是个什么东西?逗号运算符(b, a)会返回最后一个值也就是a(此时a是1),所以2[b, a]等价于2[1]。但问题来了:let声明的变量存在暂时性死区,在变量完成初始化之前访问它就会报错。这里解析器在处理2[b, a]的时候,b还没完成赋值(因为整个赋值语句let b = ...还在执行),所以就抛出了ReferenceError: Cannot access 'b' before initialization。
解决办法有这几种:
- 给变量声明手动加好分号(最直观的方式):
let a = 1; let b = 2; [b, a] = [a, b]; console.log([a, b]); // 输出 [2, 1]
- 在解构赋值行开头加个分号(很多前端开发者用来规避ASI问题的小技巧):
let a = 1 let b = 2 ;[b, a] = [a, b] console.log([a, b])
- 用括号包裹解构语句:
let a = 1 let b = 2 ([b, a] = [a, b]) console.log([a, b])
总结一下:JavaScript的ASI不是万能的,当代码行开头是[、(这类符号时,一定要注意手动分隔代码,避免解析器把两行代码合并成奇怪的表达式!
内容的提问来源于stack exchange,提问作者duginsea
相关产品推荐
相关产品推荐

