JavaScript 中对象转原始值规则
在 javascript 的隐式类型转换中,对象转原始值的规则取决于操作符的类型。对于加法运算符(+),引擎会优先调用 valueof(),若结果非原始值则再调用 tostring();而对于减法、比较等算术或关系运算,则优先调用 tostring(),若结果非原始值再调用 valueof()。这一差异决定了最终参与计算的原始值是什么。

为什么加法运算优先调用 valueOf?
加法运算符(+)在遇到对象时,优先尝试获取其数值表示,因此先调用 valueOf()。如果 valueOf() 返回的是原始值,则直接使用该值进行拼接或相加;如果返回的是对象,则继续调用 toString()。这种设计使得自定义数值类型的对象在加法中能保持数值语义。

let obj = { valueOf: () => 1, toString: () => '1' };
console.log(obj + 1); // 输出 2
obj = { valueOf: () => ({ }), toString: () => '1' };
console.log(obj + 1); // 输出 "11"
为什么减法运算优先调用 toString?
减法运算符(-)及其他算术/关系运算优先调用 toString(),因为这类运算通常期望字符串到数字的转换路径,或者更倾向于对象的文本描述。如果 toString() 返回原始值,则直接转换;否则回退到 valueOf()。这使得日期对象在减法中默认转换为时间戳字符串,进而转为数字。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

let date = new Date();
console.log(date - 0); // 输出时间戳数字
obj = { toString: () => '5', valueOf: () => 10 };
console.log(obj - 1); // 输出 4
Symbol.toPrimitive 如何覆盖默认行为?
当对象定义了 [Symbol.toPrimitive] 方法时,它会完全接管原始值转换过程。该方法接收一个提示参数('number'、'string' 或 'default'),开发者可根据提示返回任意原始值。这为自定义类型提供了精确控制转换逻辑的能力,避免了默认的 valueOf/toString 优先级问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










