You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中加法运算为何优先调用对象的valueOf而非toString的技术疑问

JavaScript中加法运算为何优先调用对象的valueOf而非toString的技术疑问

嘿,这个问题戳中了JavaScript加法运算里一个超容易踩的坑!我当初刚啃ES规范的时候也被这个逻辑绕晕过,先直接看你的代码:

console.log("12"+ {"x":"1",toString(){return 10;},valueOf(){return 90}});

你预期结果是"1210"(调用toString()),但实际输出是"1290"(调用valueOf()),核心问题出在你对加法运算的类型转换hint参数理解偏差上——加法运算给ToPrimitive的hint是default,而不是你以为的string。

先拆解ES规范里的加法运算核心逻辑(对应你提到的12.8.3章节):

  • 先把左右两个操作数都转换为原始值(调用ToPrimitive),这里的关键是:加法运算给ToPrimitive传递的hint参数是default,不是string;
  • 拿到两个原始值后,如果其中一个是字符串,就把另一个也转成字符串做拼接;否则做数字加法。

那ToPrimitive在hint为default时的规则是什么呢?

  • 对于普通对象(非Date),default hint等价于number hint:先尝试调用对象的valueOf(),如果返回的是原始值(比如你的例子里返回90,是数字原始值),就直接用这个值;如果valueOf()返回的还是对象,才会去调用toString();
  • 只有Date对象是例外,default hint对Date来说等价于string hint,会优先调用toString()。

回到你的代码:

  • 右边的普通对象,ToPrimitive用default hint,先执行valueOf()返回90(原始值);
  • 左边是字符串"12",所以把90转成字符串"90",拼接后就是"1290"。

为了验证这个逻辑,我们可以改一下代码,让valueOf()返回一个对象:

console.log("12"+ {"x":"1",toString(){return 10;},valueOf(){return {}}});

这时候valueOf()返回的不是原始值,就会 fallback 到toString(),输出结果就是你预期的"1210"。

再对比一个明确用string hint的场景,比如直接用String()构造函数:

console.log(String({"x":"1",toString(){return 10;},valueOf(){return 90}}));

这里ToPrimitive的hint是string,会直接优先调用toString(),输出"10"。

最后把规范里的关键内容贴出来帮你巩固:

12.8.3 The Addition Operator ( + )
NOTE
The addition operator either performs string concatenation or numeric addition.
12.8.3.1 Runtime Semantics: Evaluation
AdditiveExpression: AdditiveExpression + MultiplicativeExpression

  1. 计算左操作数的引用lref,获取其值lval;
  2. 计算右操作数的引用rref,获取其值rval;
  3. 将lval转换为原始值lprim,调用ToPrimitive(lval, "default");
  4. 将rval转换为原始值rprim,调用ToPrimitive(rval, "default");
  5. 如果lprim或rprim是字符串,则将另一个原始值转换为字符串并执行拼接;否则将两个原始值转换为数字并执行加法。

7.1.1 ToPrimitive(input [, PreferredType])

  • 若PreferredType为default,对于普通对象,等价于PreferredType为number;对于Date对象,等价于string;
  • 对于PreferredType为number的情况:先调用input.valueOf(),若返回原始值则使用该值;否则调用input.toString(),若返回原始值则使用该值;否则抛出TypeError。

这样是不是就把逻辑理得明明白白了?下次遇到加法运算的类型转换,先想清楚ToPrimitive的hint参数是什么,就不会踩坑啦!

备注:内容来源于stack exchange,提问作者Achiyant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 14:23:10