为什么在字符串连接操作中不调用Number.toString()?

Hum*_*rto 4 javascript string prototype

在尝试Object.toString()函数的默认行为时,我注意到下面的字符串连接可预测地调用toString()目标对象:

var x = { toString: () => "one" };
var y = { toString: () => "two" };
var output = 'x is ' + x + ' while y is ' + y;
console.log(output); // writes "x is one while y is two" to the console
Run Code Online (Sandbox Code Playgroud)

然而,当相同的,未观察到toString()在的原型被覆盖NumberBoolean,例如.toString()为了获得所需的输出,必须"强制" 调用:

Number.prototype.toString = () => "42";
Boolean.prototype.toString = () => "whatever you wish";

var a = 1;
console.log('The answer is ' + a); // writes "The answer is 1"
console.log('The answer is ' + a.toString()); // writes "The answer is 42"

var b = true;
console.log('Girl you know it\'s ' + b); // writes "Girl you know it's true"
console.log('Girl you know it\'s ' + b.toString()); // writes "Girl you know it's whatever you wish"
Run Code Online (Sandbox Code Playgroud)

这在浏览器中是一致的(在Chrome,Firefox和Edge上测试),因此我认为它是标准行为.它在哪里记录?是否有在字符串连接期间获得特殊处理的标准对象列表?

Que*_*tin 7

JavaScript将在数字原语和数字对象之间自由转换.

如果您查看运营商规则,+您会看到它说:

7让lprim为ToPrimitive(lval).

9让rprim为ToPrimitive(rval).

因此,在处理+它时,将尝试使用对象上的基元.

然后它具有ToString规则以将基元转换为字符串.

编号见7.1.12.1.

......然后描述了一个长长的特例.


简而言之:

它将值转换为基元,然后具有将数字转换为字符串的特殊情况规则.

这意味着它不会将其视为Object或调用.toString通常可以覆盖此类规则的方法.