62 lines
2.1 KiB
Markdown
62 lines
2.1 KiB
Markdown
# 逗号表达式与结构标准化
|
|
|
|
这份文档用于处理 `SequenceExpression`、表达式语句、`if`/`for` 中的逗号表达式,以及部分可安全收敛的结构标准化。
|
|
|
|
## 总原则
|
|
|
|
- 不要把所有逗号表达式都统一拆成多条语句。
|
|
- 必须先看父节点,再决定改写方式。
|
|
- 必须保证执行顺序和副作用顺序不变。
|
|
|
|
## 按父节点判断
|
|
|
|
### `ExpressionStatement`
|
|
|
|
- 通常可以直接拆成多条表达式语句。
|
|
- 但如果末尾结果还被后续逻辑隐式依赖,先确认再拆。
|
|
|
|
### `IfStatement.test`
|
|
|
|
- `if (a(), b(), test)` 可以改写为:
|
|
1. 先把 `a()`、`b()` 提到 `if` 之前。
|
|
2. 保留 `if (test)`。
|
|
|
|
### `ForStatement.init`
|
|
|
|
- `for (a(), b(), c(); test; update)` 中的 `init` 逗号表达式最适合先拆,因为它只执行一次。
|
|
|
|
### `ForStatement.test`
|
|
|
|
- `for (init; a(), b(), test; update)` 可以改写为:
|
|
1. 保留循环头里的稳定部分。
|
|
2. 把 `a()`、`b()` 放到循环体开头。
|
|
3. 在顶部加基于 `test` 的 `break` 守卫。
|
|
|
|
### `ForStatement.update`
|
|
|
|
- 只在循环体中不存在 `continue` 风险时再拆。
|
|
- 如果存在 `continue`,把更新表达式搬到循环体尾部可能会改变行为,应保守跳过。
|
|
|
|
### `ReturnStatement` 与 `VariableDeclarator`
|
|
|
|
- 这两类需要分别处理,不能简单套用表达式语句的拆法。
|
|
- 如果暂时没有足够稳定的模板,宁可不动。
|
|
|
|
## 可顺手清理的结构
|
|
|
|
- 零参数、立即执行、纯包裹的 IIFE。
|
|
- 表达式语句里的简单三元噪声。
|
|
- 可静态确认且不改变副作用顺序的简单逻辑表达式语句。
|
|
|
|
## 不要做的事
|
|
|
|
- 不要把复杂 `LogicalExpression` 默认改写成 `if`。
|
|
- 不要在不知道父节点语义的情况下使用批量 `replaceWithMultiple`。
|
|
- 不要只因为“文本更好看”就重排表达式执行顺序。
|
|
|
|
## 验证建议
|
|
|
|
- 结构标准化后立即重新 parse。
|
|
- 对 `for.test` 和 `for.update` 的改写,优先用代表性样本回归一次。
|
|
- 如果改写后只提升了少量可读性,却增加了行为不确定性,就回退。
|