我知道当JS尝试将对象表示为原始对象时,它会在对象上调用valueOf
方法。但今天我发现它在同样的情况下也调用toString()
方法:
var o = {};
o.toString = function() {return 1};
1+ o; // 2
为什么呢?如果我添加valueOf
方法,则不会调用toString
。
答案 0 :(得分:10)
我想解释的原因在于ECMA-262 specification的8.6.2.6章节:
8.6.2.6 [DefaultValue]
[...]
当使用提示编号调用O的[[DefaultValue]]方法时,将执行以下步骤:
使用参数" valueOf"调用对象O的[[Get]]方法。
如果结果(1)不是对象,请转到步骤5.
如果Result(3)是原始值,则返回Result(3)。
使用参数" toString"调用对象O的[[Get]]方法。
如果结果(5)不是对象,请转到步骤9。
由于您的对象没有实现valueOf,因此使用toString。
答案 1 :(得分:9)
一切都取决于提示。
当您使用1 + o
时,由于+
操作数,它是一个数字提示,因此在valueOf
之前肯定会使用toString
。
如果提示是字符串,则在toString
之前使用valueOf
。例如,尝试["o",o].join("=")
一起将是:
var o = {};
o.toString = function() {return 1};
o.valueOf= function(){return 2};
1 + o; // 1+2=3 ==> it takes valueOf value
["o",o].join("") //o1 ==> it takes toString value
答案 2 :(得分:5)
<强> TL; DR 强>
当调用ToPrimitive而没有hint
时,它就像提示是number
一样。这定义了要调用的方法:首先valueOf
然后toString
。如果您尚未定义自己的valueOf
,则会调用Object.prototype.valueOf
来返回此内容。
BTW在现代浏览器中你可以更具体地了解它
const a = {
[Symbol.toPrimitive]: function(hint) {
console.log(hint);
return {
'default': 1,
'number': 2,
'string': 'three'
}[hint]
}
}
console.log(a + 1); //default, 2
console.log(+a + 1); //number, 3
console.log(`${a} + one`); //string, three + one
长读: