在 javascript 中,当使用加号 (+) 连接字符串时
另一个变量,如果它不是 string
,该变量将隐式调用其 toString
方法。为了验证这一点,我制作了一个名为 Apple 的构造函数。
function Apple(name) {
this.name = name;
}
Apple.prototype.toString = function() {
console.log('Apple.prototype.toString called.');
return this.name;
};
var apple = new Apple('Thai apple');
var msg = apple + ' tastes good.'
console.log(msg)
它按我的预期工作:在计算 apple + 'tastes good'
时,
Apple.prototype.toString
被调用。
然后我在 Number
类型上做了一个类似的实验。
Number.prototype.num2str = Number.prototype.toString;
Number.prototype.toString = function() {
console.log('new Number.prototype.toString called.');
return this.num2str();
}
var msg = 'num = ' + 123;
console.log(msg);
运行后,我注意到 Number.prototype.toString
没有被调用。
我很困惑。为什么它不像前面的示例那样工作?
最佳答案
Why doesn't it work like the previous example?
toString
仅在值为对象 时调用(但请参阅下文)。 123
不是一个对象,它是一个原始(数字)值。将原始值转换为字符串值遵循不同的规则。参见 §7.1.12
在 ES2016 规范中,和 §7.1.12.1
特别是关于如何将值转换为字符串的数字(此处引用太长)。
当使用 +
运算符时,原始值不会强制转换为对象。
但是,即使您创建了一个数字对象,它也不会起作用。那是因为 toString
实际上并没有为数字对象调用。这是为什么?
When performing additio n,发生以下步骤:
[...]
5. Let lprim be ? ToPrimitive(lval).
6. Let rprim be ? ToPrimitive(rval).
[...]
这两个值首先被转换为原始值之前它们被转换为数字或字符串(原始值可以是字符串、数字、 bool 值、null
或 undefined
)。
以这种方式将对象 转换为原始值最终将首先调用valueOf
。仅当该函数的返回值不是原始值时才会调用toString
。
因为 new Number(123).valueOf()
返回原始值,所以 toString
不会被调用!
这是针对 valueOf
调整的示例:
Number.prototype.valueOf = function() {
console.log('new Number.prototype.valueOf called.');
return 'something';
}
var msg = 'num = ' + new Number(123);
console.log(msg);
NB: toString
和 valueOf
实际上是将对象转换为字符串/数字/基元的过时方法。从ES6开始,新的是调用对象的@@toPrimitve
方法。只有当它不存在时,才会调用 toString
或 valueOf
(请参阅 §7.1.1 ToPrimitive
)。
关于javascript - 为什么修改 Number.prototype.toString 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43262266/