让我们看一下这些例子:
var a = 1;
var b = { toString:function() {return '1'} };
var c = 1;
a + b + c === "111" // true
非常令人兴奋。我知道当我们使用+运算符时,JS解释器执行ToPrimitive或ToString操作。但是,当没有提示PreferredType时,为什么对象b会转换为字符串。因此它可能使用ToString操作。
另一个注意事项:如果对象上存在toString方法,它只会被转换为字符串,为什么?如果我将该方法称为“toNumber”,为什么它不会转换为数字?
为什么JavaScript会像那样?
答案 0 :(得分:7)
但是,当没有提示PreferredType时,为什么对象b会转换为字符串。
如果没有提交提示,则首先调用对象的valueOf
方法。但由于b.valueOf()
没有返回原始值(默认情况下它返回对象本身),因此将调用b.toString()
。
请参阅specification。
转换规则可归纳如下:
number
没有提示或提示,请先致电valueOf
。string
,请先致电toString
。如果对象上存在toString方法,它只会转换为字符串,为什么?
不确定我理解这句话。每个对象都有toString
方法。如果您尝试在没有toString
方法的对象上执行此操作(通过Object.create(null)
),则会引发错误。
如果我将该方法称为" toNumber",为什么不将其转换为数字?
因为toNumber
在JavaScript中没有意义。 toString
和valueOf
是两个"魔法"将对象转换为基元的方法:
var n = 1;
var o = {
toString() { return 'bar'; },
valueOf() { return 2; }
};
console.log(n + o);
console.log(String(o));

如果这些方法都没有返回原语,那么你也会收到错误。
var n = 1;
var o = {
toString() { return this; },
};
console.log(n + o);

这两种方法及其命名似乎有点武断。从ES6开始,定义转换函数的首选方法是使用众所周知的@@toPrimitive
符号:
var a = 1;
var b = { [Symbol.toPrimitive]: function() {return 1} };
var c = 1;
console.log(a + b + c);

在调用
@@toPrimitive
或valueOf
之前调用 toString
。
为什么JavaScript表现得那样?
因为它是如何在规范中定义的。如果您想知道背后的理由,您必须询问做出该决定的人。