为什么JavaScript表现得那样?

时间:2016-12-07 01:08:54

标签: javascript coercion

让我们看一下这些例子:

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会像那样?

1 个答案:

答案 0 :(得分:7)

  

但是,当没有提示PreferredType时,为什么对象b会转换为字符串。

如果没有提交提示,则首先调用对象的valueOf方法。但由于b.valueOf()没有返回原始值(默认情况下它返回对象本身),因此将调用b.toString()

请参阅specification

转换规则可归纳如下:

  • 如果number没有提示或提示,请先致电valueOf
  • 如果提示为string,请先致电toString
  • 如果返回值不是原始值,则调用另一个方法。
  • 如果返回值仍不是原始值,则抛出错误。
  

如果对象上存在toString方法,它只会转换为字符串,为什么?

不确定我理解这句话。每个对象都有toString方法。如果您尝试在没有toString方法的对象上执行此操作(通过Object.create(null)),则会引发错误。

  

如果我将该方法称为" toNumber",为什么不将其转换为数字?

因为toNumber在JavaScript中没有意义。 toStringvalueOf是两个"魔法"将对象转换为基元的方法:



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




在调用@@toPrimitivevalueOf之前调用

toString

  

为什么JavaScript表现得那样?

因为它是如何在规范中定义的。如果您想知道背后的理由,您必须询问做出该决定的人。