JavaScript算术运算隐式转换规则:+优先字符串拼接,其余运算符强制转数字;对象先ToPrimitive再转换;布尔值、null、undefined有固定数字映射;所有转换严格遵循ECMAScript规范步骤。

JavaScript在算术运算中会自动进行隐式类型转换,但**只发生在操作数不是数值类型时**,且转换规则严格依赖于运算符和操作数的原始类型。核心逻辑是:先尝试转为数字,失败则转为字符串(仅限+),其他算术运算符(-、*、/、%)强制要求数字上下文,无法转数字就返回NaN。
加法(+)的双重语义:数字相加 or 字符串拼接
+是唯一有“重载”行为的算术运算符。它先检查两个操作数是否**至少有一个是字符串**,若是,则全部转为字符串并拼接;否则才尝试转为数字后相加。
-
1 + "2"→"12"(字符串优先,1转"1") -
1 + true→2(true转1,无字符串,走数字路径) -
1 + [2, 3]→"12,3"(数组[2,3]转字符串"2,3",触发拼接) -
null + undefined→NaN(两者转数字分别是0和NaN,0 + NaN === NaN)
减法、乘法、除法、取余:严格数字模式
这些运算符不支持字符串拼接,会**统一调用ToNumber抽象操作**将操作数转为数字。转换失败即得NaN,且NaN参与任何算术运算结果仍是NaN。
-
"5" - "2"→3(字符串成功转数字) -
"5" * []→0(空数组[]转数字为0) -
true / false→Infinity(true→1,false→0,1/0) -
{} - []→NaN(对象{}转原始值失败,ToNumber({}) === NaN)
对象到原始值的转换是关键中间步骤
当操作数是对象(如数组、日期、普通对象)时,JavaScript不会直接转数字或字符串,而是先调用[[ToPrimitive]]内部方法,尝试用valueOf()或toString()获取原始值,再对结果进行类型转换。
立即学习“Java免费学习笔记(深入)”;
-
[1] + [2]→"12"(两数组分别toString()得"1"和"2",再拼接) -
Date.now() + new Date()→ 拼接时间戳和字符串形式日期(Date对象toString()优先于valueOf()) -
({} + {})→"[object Object][object Object]"(默认toString()) - 若自定义
valueOf()返回数字,如let obj = { valueOf(){return 42;} };,则obj * 2 === 84
布尔值、null、undefined 的固定映射
这些原始类型有明确的数字等价:true→1、false→0、null→0、undefined→NaN。注意null和undefined在+中表现不同——null + 1 === 1,而undefined + 1 === NaN。
-
null == 0为true,但null === 0为false(比较时也触发隐式转换) -
Boolean(null)是false,但Number(null)是0,体现类型转换与布尔转换逻辑分离 -
+"0"、+" "、+"0x10"都合法(分别得0、0、16),而+"hello"得NaN
隐式转换不是“随意猜测”,而是遵循ECMAScript规范定义的确定步骤:运算符决定目标类型 → 操作数经ToPrimitive转原始值 → 原始值再经ToNumber或ToString处理。理解这个链条,就能预判绝大多数奇怪结果。










