- 09-loops: finish exercises A-F - 00-concepts: add semicolons-and-asi.md (when ; is mandatory: line starting with ( or [, no newline after return/throw) - README: index the new concept notepull/1034/head
parent
e9fb78c3f3
commit
a2e55346a5
@ -0,0 +1,81 @@
|
||||
# 通用概念 · 分号 `;`:什么时候【必须】写
|
||||
|
||||
> JS/TS 每句结尾的 `;` 绝大多数可省(引擎会自动补),但**有几种情况不写就是坑**。
|
||||
> 本篇只记"**必须写、不写就出 bug**"的场景。相关:`../09-loops.js`(无分号风格)。
|
||||
|
||||
## 背景:ASI —— 引擎会自动补分号
|
||||
|
||||
JS 有个机制叫 **ASI(Automatic Semicolon Insertion,自动分号插入)**:
|
||||
你不写 `;`,引擎在换行处**通常**会替你补上。所以这两种写法行为完全一样:
|
||||
|
||||
```js
|
||||
const a = 1; // 写了
|
||||
const a = 1 // 没写,ASI 自动补 —— 等价
|
||||
```
|
||||
|
||||
> 本仓库 `js_notes/` 统一用**无分号**风格(Prettier 默认),保持一致即可,别混着来。
|
||||
> 但无分号的前提是:**知道下面这几个 ASI 会猜错的地方,主动兜底。**
|
||||
|
||||
## ⚠️ 坑 1:下一行以 `(` 或 `[` 开头 → 必须在【行首】补 `;`
|
||||
|
||||
ASI 看到下一行还能和上一行"连成一句",就**不补**分号,于是两行被黏成一句:
|
||||
|
||||
```js
|
||||
// 💥 出错: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 当函数调用
|
||||
```
|
||||
|
||||
**正解:在以 `(` / `[` 开头的那行,行首加 `;`**(不是上一行结尾):
|
||||
|
||||
```js
|
||||
const x = 5
|
||||
;[1, 2, 3].forEach((n) => console.log(n)) // ✅ 行首 ; 把两句切开
|
||||
```
|
||||
|
||||
口诀:**一行别以 `(` 或 `[` 开头;非要这么写,行首先放一个 `;`。**
|
||||
(常见于:上一行是赋值/表达式,下一行想直接 `[...]`.map() 或 `(...)` 立即执行。)
|
||||
|
||||
## ⚠️ 坑 2:`return` / `throw` 等后面【不能】换行
|
||||
|
||||
这几个关键字后面一旦换行,ASI 会**强制**在关键字后补 `;`,把真正想返回的东西丢掉:
|
||||
|
||||
```js
|
||||
// 💥 等于 return; 换行后的对象被当成"死代码"丢弃 → 函数返回 undefined
|
||||
function make() {
|
||||
return
|
||||
{ name: 'Tom' }
|
||||
}
|
||||
make() // undefined,不是那个对象!
|
||||
```
|
||||
|
||||
**正解:要返回的东西和 `return` 写在同一行**(对象太长就用括号包起来接着写):
|
||||
|
||||
```js
|
||||
function make() {
|
||||
return { name: 'Tom' } // ✅ 同一行
|
||||
}
|
||||
```
|
||||
|
||||
同样受影响的:`return` / `throw` / `break` / `continue` / `yield` —— **后面别换行**。
|
||||
|
||||
## ⚠️ 坑 3(顺带):同一行写两句,中间【必须】有 `;`
|
||||
|
||||
分号真正的本职工作是"分隔语句"。想把两句挤在一行,中间**必须**加 `;`:
|
||||
|
||||
```js
|
||||
let a = 1 let b = 2 // 💥 语法错误
|
||||
let a = 1; let b = 2 // ✅ 一行两句,靠 ; 分隔
|
||||
```
|
||||
|
||||
## ✅ 一句话
|
||||
|
||||
> 平时跟着仓库的**无分号**风格写就行,ASI 帮你兜底。只死记两条保命规则:
|
||||
> 1. **行首是 `(` 或 `[`** → 这一行**行首**补 `;`;
|
||||
> 2. **`return`/`throw`/`break`/`continue` 后面不换行**(要返回的写同一行)。
|
||||
>
|
||||
> 装了 Prettier 的话,保存时会自动帮你处理坑 1 的行首 `;`,更省心。
|
||||
> TS 规则完全一样(TS 是 JS 超集),只是 TS 项目社区**更偏爱每句都写 `;`** —— 那是团队约定,不是语法强制。
|
||||
Loading…
Reference in new issue