为什么 JavaScript 会这样?

Why JavaScript behaves like that?

让我们看看这些例子:

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 会这样?

But why is object b gets converted to a string when there is no hint PreferredType.

当没有传递提示时,对象的valueOf方法将首先被调用。但是由于 b.valueOf() 不是 return 原始值(默认情况下它 return 是对象本身),接下来将调用 b.toString()

参见specification

转换规则可以总结如下:

  • 如果没有提示或提示是number,先调用valueOf
  • 如果提示是string,先调用toString
  • 如果 return 值不是原始值,则调用其他方法。
  • 如果 return 值仍然不是原始值,则抛出错误。

it is only gets converted to string if there is toString method exists on object, why?

不确定我是否理解此声明。每个对象都有一个 toString 方法。如果您尝试在没有 toString 方法(通过 Object.create(null))的对象上执行此操作,则会抛出错误。

And if I call that method "toNumber", why it is not converted to number?

因为toNumber在JavaScript中没有意义。 toStringvalueOf 是两个 "magic" 方法,通过它们将对象转换为基本类型:

var n = 1;
var o = {
  toString() { return 'bar'; },
  valueOf() { return 2; }
};

console.log(n + o);
console.log(String(o));

如果方法 none 中的 return 是原语,你也会得到一个错误。

    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);

在调用 valueOftoString 之前调用

@@toPrimitive

Why JavaScript behaves like that?

因为规范中就是这样定义的。如果你想知道这背后的理由,你必须问做出那个决定的人。