一个没有手动加分号引发的bug

最近因为分号的疏忽,导致出现了一个bug,记录下来,分享给大家。

1、一个示例

给你下面这一段代码,你根据经验判断一下运营结果

scss 复制代码
let [a,b] = ['a','b']
let [x,y] = [1,2]
if(x < y){
    [x,y] = [y,x]
    [a,b] = [b,a]
}

按照一般的理解,是不是应该是 x = 2,y=1,a = 'b',b = 'a' ? 可实际呢?咱们跑一下看看:

css 复制代码
console.log([x,y]) // ['b', 'a']
console.log([a,b]) // ['a','b']

2、为什么呢?

这段代码不加分号会导致 [x,y][a,b] 被错误解析为一个连续表达式,从而引发赋值错误。根本原因是 JavaScript 的 自动分号插入(ASI) 机制在以下情况 不会插入分号

  1. 当下一行以 [ 开头时,会被解析为当前语句的延续
  2. 赋值表达式可以跨行解析

3、错误解析过程(无分号时):

javascript 复制代码
if(x < y){
    [x,y] = [y,x]  // 注意这里没有分号
    [a,b] = [b,a]  // 被解析为上一行的延续
}

JavaScript 引擎会将其解析为:

javascript 复制代码
[x,y] = [y,x][a,b] = [b,a]

这实际等价于:

javascript 复制代码
// 1. 先计算 [y,x][a,b]
// - [y,x] 是一个数组 [2, 1] 
// - [a,b] 是逗号表达式,返回最后一个值 'b'
const temp = [y,x]['b'] // 相当于访问数组的 'b' 属性
// 2. 将 [b,a] 赋值给上述结果
temp = [b,a]
// 再将 temp 赋值给 [x,y] 
[x,y] = temp
// 也就是
[x,y] = [b,a]

最终导致 xy 被赋值为 [b,a](即 ['b','a']

4、加分号后验证代码:

javascript 复制代码
let [a,b] = ['a','b'];  // a='a', b='b'
let [x,y] = [1,2];      // x=1, y=2

if(x < y){
    [x,y] = [y,x];      // 正常交换:x=2, y=1
    [a,b] = [b,a];      // 正常交换:a='b', b='a'
}

console.log(x, y); // 输出: 2 1
console.log(a, b); // 输出: b a

5、解决方案:

5.1. 始终添加分号(推荐)

javascript 复制代码
// 正确写法
[x,y] = [y,x]; // 明确分号结束
[a,b] = [b,a];

5.2. 使用防御性分号

javascript 复制代码
// 在可能引起歧义的语句前加分号
;[a,b] = [b,a]

5.3. 用逗号写成单行

javascript 复制代码
// 单行写法避免换行问题
if(x < y){ [x,y] = [y,x], [a,b] = [b,a] }

6、关键教训:

  1. 避免以 [( 开头的行

    这类语法结构容易与前一行的表达式粘连

  2. 解构赋值后必须加分号

    特别是在块语句(if/for 等)内部

  3. 使用 ESLint 规则

    配置 semi: ["error", "always"] 强制分号使用:

    json 复制代码
    // .eslintrc.json
    {
      "rules": {
        "semi": ["error", "always"]
      }
    }
相关推荐
薛定猫AI3 小时前
【深度解析】Gemma Chat 本地 AI 编程 Agent:Electron + MLX + 开源模型的离线 Vibe Coding 实战
javascript·人工智能·electron
kyriewen3 小时前
Webpack vs Vite:一个是“老黄牛”,一个是“猎豹”,你选谁?
前端·webpack·vite
打小就很皮...3 小时前
html2canvas + jsPDF 生成 PDF 的踩坑与解决方案总结
前端·pdf
全栈前端老曹3 小时前
【前端地图】多地图平台适配方案——高德、百度、腾讯、Google Maps SDK 差异对比、封装统一地图接口
前端·javascript·百度·dubbo·wgs84·gcj-02·bd09
笑虾3 小时前
Win10 修改注册表 让鼠标悬停PNG上时 tip 始终显示分辨率
开发语言·javascript·ecmascript
雾岛听风6913 小时前
JavaScript基础语法速查手册
开发语言·前端·javascript
遇见~未来4 小时前
第三篇_现代布局_从弹性到网格
前端·css3
前端那点事4 小时前
Vue前端SEO优化全攻略(实操落地版,新手也能上手)
前端·vue.js
Dxy12393102164 小时前
HTML 如何使用 SVG 画曲线
前端·算法·html
用户2367829801684 小时前
从零实现 GIF 制作工具:LZW 压缩与 Median Cut 色彩量化
前端·javascript