You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.0 KiB
3.0 KiB
通用概念 · 分号 ;:什么时候【必须】写
JS/TS 每句结尾的
;绝大多数可省(引擎会自动补),但有几种情况不写就是坑。 本篇只记"必须写、不写就出 bug"的场景。相关:../09-loops.js(无分号风格)。
背景:ASI —— 引擎会自动补分号
JS 有个机制叫 ASI(Automatic Semicolon Insertion,自动分号插入):
你不写 ;,引擎在换行处通常会替你补上。所以这两种写法行为完全一样:
const a = 1; // 写了
const a = 1 // 没写,ASI 自动补 —— 等价
本仓库
js_notes/统一用无分号风格(Prettier 默认),保持一致即可,别混着来。 但无分号的前提是:知道下面这几个 ASI 会猜错的地方,主动兜底。
⚠️ 坑 1:下一行以 ( 或 [ 开头 → 必须在【行首】补 ;
ASI 看到下一行还能和上一行"连成一句",就不补分号,于是两行被黏成一句:
// 💥 出错:ASI 不补,被理解成 5[1,2,3]... 或 b(...)
const x = 5
[1, 2, 3].forEach((n) => console.log(n)) // TypeError: Cannot read properties...
const b = foo
(function () {})() // foo(function(){})() —— 把 foo 当函数调用
正解:在以 ( / [ 开头的那行,行首加 ;(不是上一行结尾):
const x = 5
;[1, 2, 3].forEach((n) => console.log(n)) // ✅ 行首 ; 把两句切开
口诀:一行别以 ( 或 [ 开头;非要这么写,行首先放一个 ;。
(常见于:上一行是赋值/表达式,下一行想直接 [...].map() 或 (...) 立即执行。)
⚠️ 坑 2:return / throw 等后面【不能】换行
这几个关键字后面一旦换行,ASI 会强制在关键字后补 ;,把真正想返回的东西丢掉:
// 💥 等于 return; 换行后的对象被当成"死代码"丢弃 → 函数返回 undefined
function make() {
return
{ name: 'Tom' }
}
make() // undefined,不是那个对象!
正解:要返回的东西和 return 写在同一行(对象太长就用括号包起来接着写):
function make() {
return { name: 'Tom' } // ✅ 同一行
}
同样受影响的:return / throw / break / continue / yield —— 后面别换行。
⚠️ 坑 3(顺带):同一行写两句,中间【必须】有 ;
分号真正的本职工作是"分隔语句"。想把两句挤在一行,中间必须加 ;:
let a = 1 let b = 2 // 💥 语法错误
let a = 1; let b = 2 // ✅ 一行两句,靠 ; 分隔
✅ 一句话
平时跟着仓库的无分号风格写就行,ASI 帮你兜底。只死记两条保命规则:
- 行首是
(或[→ 这一行行首补;;return/throw/break/continue后面不换行(要返回的写同一行)。装了 Prettier 的话,保存时会自动帮你处理坑 1 的行首
;,更省心。 TS 规则完全一样(TS 是 JS 超集),只是 TS 项目社区更偏爱每句都写;—— 那是团队约定,不是语法强制。