JavaScript算术运算中加法+有字符串优先逻辑,其余运算符统一转数字:+遇字符串则拼接,否则转数字相加;-、*、/、%一律ToNumber后计算,无效转换结果为NaN。

JavaScript中算术运算(如 +、-、*、/、%)会触发隐式类型转换,但规则并不统一:加法 + 有字符串优先逻辑,其余运算符则强制转为数字。
加法 + 的特殊双路径逻辑
当使用 + 时,JS 先尝试字符串拼接,仅当两边都不是原始字符串时才走数值相加:
- 只要任一操作数是字符串(或可转为字符串的原始值),整个表达式按字符串拼接处理:
"2" + 3 → "23",true + "1" → "true1" - 若两个操作数都不是字符串(且非
null或undefined),才调用ToNumber转换后相加:2 + null → 2(null转为0),2 + undefined → NaN(undefined转为NaN) -
+运算符本身不改变操作数类型,但会触发ToString或ToNumber抽象操作,具体取决于“是否能走字符串分支”
减法、乘法、除法、取余统一走数字路径
这些运算符没有字符串拼接语义,一律先将操作数通过 ToNumber 转为数字,再计算:
-
"2" - "1" → 1(两边转为2和1) -
true * "3" → 3(true → 1,"3" → 3) -
{} - [] → 0(空对象{}调用toString()得"[object Object]",转数字为NaN;空数组[]转字符串为"",再转数字为0;最终NaN - 0 → NaN—— 实际结果是NaN,不是0,此处需修正:正确示例应为[] - [] → 0,因为[] → "" → 0) - 任何无法有效转为数字的值(如
"abc"、{}、function(){})都会变成NaN,导致整个结果为NaN
ToNumber 转换的关键细节
算术运算中非数字操作数的转换,依赖 ECMAScript 规范定义的 ToNumber 抽象操作:
立即学习“Java免费学习笔记(深入)”;
-
null → 0,undefined → NaN - 布尔值:
true → 1,false → 0 - 字符串:按数字字面量解析,忽略首尾空白,空字符串
"" → 0,无效格式(如"2a")→NaN - 对象(含数组):先调用
valueOf(),若返回原始值则转数字;否则调用toString(),再对结果执行ToNumber。例如:[1,2] → "1,2" → NaN,[1] → "1" → 1,new Date() → 日期字符串 → 对应时间戳数字
避免意外转换的实用建议
隐式转换易引发隐蔽 bug,推荐主动控制类型:
- 做加法前明确意图:拼接用
String(a) + String(b),相加用Number(a) + Number(b)或一元加号+a + +b - 对用户输入或外部数据,优先用
parseInt(str, 10)或parseFloat(str)替代隐式转换,它们对前导空格和部分数字更宽容 - 启用 ESLint 规则(如
no-implicit-coercion)提示潜在隐式转换 - 在严格模式下,虽然不禁止隐式转换,但配合 TypeScript 可在开发期捕获多数类型不匹配问题


















