我最近阅读了关于Object.prototype.valueOf() on MDN的文章,感觉他们说完全错了:
valueOf()
方法返回指定对象的原始值。
我的意思是,如果我们讨论这个方法的更具体的版本,例如String.prototype.valueOf()
,这个句子会有所帮助,它在原型链中更接近,因此将被调用而不是{{ 1}}方法,当调用Object.prototype
对象的valueOf
方法时。在这种情况下,将运行内部算法String
,并返回对象的内部属性thisStringValue
的值,即原始字符串值。所以这确实是从对象到原始值的转换。
但据我所知,[[StringData]]
valueOf
方法通过调用内部方法Object.prototype
完全符合相反方式。
现在,如果在普通对象上调用ToObject
,它将调用Object.prototype.valueOf()
传递方法的this值,该值指向对象本身,在这种情况下,{{1}只会返回对象的引用,该引用通过ToObject
显示为ToObject
。
假设我们用toString()
的相关方法覆盖[object Object]
的值,然后通过调用构造函数创建一个String.prototype.valueOf()
对象。 - 如果我们现在调用Object.prototype
,我们会得到一个对象,而不是我们作为参数传入的原始字符串值。 String
中只有valueOf()
,没有从对象到原始值的转换,就我所见。
所以我做对了,他们错了,或者是我不懂的?
答案 0 :(得分:2)
valueOf()
方法返回指定对象的原始值。
请记住,MDN是由你和我这样的凡人写的。我不会选择这种方式来总结valueOf
。一个更有意义的总结(借用下面的“描述”):
valueOf()
方法返回当指定对象需要强制转换为基元时要使用的值。
MDN页面上的其余描述对我来说似乎非常合理和清晰。
来自你的评论:
我认为将内置对象的所有valueOf方法视为一个是错误的,因为它们的行为方式不同,这在我在我的问题中链接的文章中暗示。
但文章本身说
每个内置核心对象都会覆盖此方法以返回适当的值。
所以不将它们全部视为一体。是的,有一个valueOf
接口,但它在不同的对象上有不同的实现。
说“将对象转换为原始值”这个方法是错误的
我在文章中没有看到那个确切的短语,但这对我来说是正确的。
答案 1 :(得分:1)
Object.prototype.valueOf
的目的只是作为不使用更具体的方法覆盖它的对象的默认方法。你不应该直接调用这个函数,因为当你调用一个对象的valueOf()
方法时,原因链中没有更具体的东西就会调用它。
根据定义,如果一个对象没有覆盖它,那么它的原始值"只是对象本身。
答案 2 :(得分:0)
声明并不完全准确,正如您所说的那样,它对于特定实现来说更“真实”,但它是一个摘要并解释了该方法的用意。
说“将对象转换为原始值”这个方法是错误的,
不,这是对的。更确切地说:它被称为将对象转换为数字。来自specs:
当使用参数O和提示调用抽象操作OrdinaryToPrimitive时,将执行以下步骤:
断言:类型(O)是对象
断言:Type(提示)是String及其值 是“字符串”或“数字”。
如果提示是“字符串”,那么让 methodNames是«“toString”,“valueOf”»。
否则,让methodNames成为 «“valueOf”,“toString”»。
- 醇>
对于List顺序中methodNames中的每个名称,请执行
...
III。如果Type(结果)是而不是对象,则返回结果。
- 抛出TypeError异常。
醇>
当然,无法保证valueOf
的实现实际上返回原始值,但这就是该方法的用途。如果原型链中没有其他实现,实际上甚至会调用Object.prototype.valueOf
来将对象转换为原始值。正如你所注意到的那样它不会起作用,但它仍会被调用。
您可以自己尝试一下:
var myObject = {
valueOf: function() {
console.log('valueOf');
return this;
},
toString: function() {
console.log('toString');
return this;
}
};
1 + myObject;
将打印:
valueOf
toString
Uncaught TypeError: Cannot convert object to primitive value