JavaScript加法运算遵循字符串优先原则:任一操作数为字符串则转为字符串拼接;否则全部转数字相加;对象先调valueOf再toString转换。

JavaScript在加法运算中遇到不同类型时,会按特定规则进行隐式转换,核心原则是:如果任一操作数是字符串,另一个也会转为字符串并执行字符串拼接;否则全部转为数字再相加。
字符串优先:只要有一个是字符串,就走拼接逻辑
加法运算符(+)是JavaScript中唯一具有“双语义”的运算符——既可数值相加,也可字符串拼接。引擎会先检查两个操作数中是否至少有一个是原始字符串(string),一旦满足,就将另一个操作数调用 ToString() 转换为字符串,然后拼接。
- "1" + 2 → "12"(数字2 → 字符串"2")
- true + "hello" → "truehello"(布尔true → "true")
- null + "world" → "nullworld"(null → "null")
- [1,2] + "3" → "1,23"(数组→"1,2",再拼接)
非字符串场景:统一转为数字后相加
当两个操作数都不是字符串(即都不满足 ToString 优先条件)时,引擎会对它们分别调用 ToNumber(),再执行数值加法。注意:这包括 undefined、null、布尔值、对象等,都按规范转为数字。
- 1 + true → 1 + 1 → 2(true → 1)
- null + 0 → 0 + 0 → 0(null → 0)
- undefined + 5 → NaN + 5 → NaN(undefined → NaN)
- {} + [] → "[object Object]" + "" → "[object Object]"(对象和数组先 ToString,结果都是字符串,触发拼接)
对象的转换路径:先 valueOf,再 toString
当操作数是对象(含数组、日期、自定义对象等)时,+ 运算会尝试调用其 valueOf() 方法;若返回原始值(非对象),则使用该值;否则再调用 toString()。若两者都返回对象,则抛出 TypeError(但实际中极少发生,因内置类型已确保至少一个返回原始值)。
立即学习“Java免费学习笔记(深入)”;
- [] + [] → "" + "" → ""(数组.valueOf() 返回[](对象),回退 toString() → "")
- +new Date() → 当前时间戳(毫秒数)(Date.valueOf() 直接返回数字)
- ({}) + ({}) → "[object Object][object Object]"(两个对象都 toString → 字符串,拼接)
避免陷阱的实用建议
隐式转换易引发意料之外的结果,尤其在表单输入、状态计算等场景。推荐主动控制类型:
- 明确字符串拼接:用 String(a) + String(b) 或模板字面量 `${a}${b}`
- 明确数值相加:用 Number(a) + Number(b) 或一元加号 +a + +b
- 校验输入:对用户输入或 API 数据,优先用 typeof x === 'string' 判断,再决定处理路径
- 启用严格模式 + ESLint 规则(如 no-plusplus 配合类型检查插件)可提前暴露风险










