JavaScript对象可通过自定义valueOf方法实现加减运算,引擎在算术运算中优先调用valueOf获取原始数值;ES6还可使用Symbol.toPrimitive提供更精确的类型转换控制。

JavaScript 中对象默认不能直接参与加减运算,但可以通过自定义 valueOf 方法,让引擎在需要原始值时自动调用它,从而实现两个对象的加减操作。
valueOf 的作用机制
当 JavaScript 遇到算术运算(如 +、-)时,会尝试将操作数转换为原始值(number 或 string)。转换顺序是:先调用 valueOf(),如果返回的是原始值就使用;否则再调用 toString()。因此,只要 valueOf 返回一个数字,对象就能自然参与数值运算。
实现可运算的对象类
定义一个类,在其原型上设置 valueOf,返回用于计算的数值:
示例:封装一个带数值的容器对象
class Num {
constructor(value) {
this.value = Number(value);
}
valueOf() {
return this.value;
}
}
<p>const a = new Num(10);
const b = new Num(3);</p><p>console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.333...
</p>
注意隐式转换的边界情况
加号 + 有字符串拼接优先级,若任一操作数的 valueOf 返回非数字原始值(比如字符串),或 toString 被触发且返回字符串,则结果可能是拼接而非相加:
- 确保
valueOf总是返回number类型,避免意外字符串行为 - 减法
-、乘法*、除法/等运算符强制转为数字,不会触发字符串拼接,更安全 - 若需支持
+也稳定为数值相加,可同时重写toString返回数字字符串(如return String(this.value)),但不如统一靠valueOf可靠
与 Symbol.toPrimitive 的关系
ES6 引入了 [Symbol.toPrimitive](hint),优先级高于 valueOf 和 toString。如果同时存在,引擎会根据 hint("number"、"string" 或 "default")决定调用哪个。对于算术运算,hint 是 "number",所以你可以更精确地控制:
class Num {
constructor(value) {
this.value = Number(value);
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') return this.value;
return this.value.toString(); // 其他场景(如 console.log)按需处理
}
}
这种写法更规范,兼容性也好(现代浏览器和 Node.js 均支持)。










