为何ESLint要禁止使用自增(++)、自减(--)运算符?
我完全懂你的困惑——这些运算符几乎是JavaScript入门的标配,从大学课程到各类权威文档都在教,突然被ESLint标红禁止,换谁都会纳闷“凭什么?”。其实这条规则的核心不是语法错误,而是工程化视角下的代码可维护性与bug预防,下面拆解几个关键原因:
1. 自动分号插入(ASI)带来的隐蔽陷阱
你已经注意到ASI的影响,这确实是禁止它们的核心原因之一。JavaScript的自动分号插入机制会在特定场景下悄悄补充分号,但自增/自减运算符对空格的敏感度极高,细微的空格差异会完全改变代码语义,而且这种问题很难排查。
举个真实可能踩坑的例子:
let count = 0 const nextCount = count ++ count
你可能以为nextCount会被赋值为1,但ASI会在++前插入分号,实际执行逻辑是:
let count = 0 const nextCount = count; ++count;
最终nextCount还是0,完全不符合预期。这种因空格导致的逻辑偏差,在大型项目里很容易被忽略,直到出现bug才会被发现。
2. 可读性与歧义问题
自增/自减的前置(++i)和后置(i++)差异,在简单场景下没问题,但嵌套在复杂表达式里时,很容易让开发者(尤其是团队里的新手)产生理解偏差。比如:
if (list[i++] === target) { // ... }
或者更复杂的:
const total = i++ + ++j * 2;
这种代码需要额外花时间去理清执行顺序,而如果换成明确的写法:
if (list[i] === target) { i += 1; } // 或者 const total = i + (j += 1) * 2; i += 1;
语义一目了然,不需要额外动脑去解析运算符的优先级和副作用顺序,团队协作时能大幅降低沟通成本。
3. 避免无意识的副作用
自增/自减是带副作用的表达式——它们不仅会返回一个值,还会修改变量本身。当这种操作被嵌入到函数参数、数组索引或者条件判断里时,很容易产生意外的连锁反应。比如:
const arr = [10, 20, 30]; console.log(arr[i++], arr[i]);
如果初始i=0,这段代码会打印10和20;但如果不小心写成++i,就会打印20和20。这种细微的差异很容易在编码时疏忽,而用i += 1的话,副作用是明确的单独操作,不会和其他表达式混在一起,从根源上减少这类错误。
为什么权威文档没提这些顾虑?
其实MDN、W3Schools这类文档的定位是语法说明,它们会告诉你“这个运算符怎么用”,但不会深入讨论工程化场景下的最佳实践。ESLint的规则更多是从团队长期维护、减少人为错误的角度出发,属于“可选但推荐”的规范,不是说这些运算符本身有语法问题。
当然,这条规则不是强制性的——很多项目依然在使用自增/自减运算符,尤其是在循环场景下(比如for (let i=0; i<len; i++))。但如果你的团队追求极致的代码一致性和可维护性,禁止它们确实是个能减少潜在bug的好选择。
内容的提问来源于stack exchange,提问作者Jankapunkt

