低调的 valueOf()

JavaScript Object 上的 valueOf() 方法,是不是看上去很冷门的样子?貌似都不怎么用的。但是,真的没有用到吗?

可能从命名上,你可以了解到它可以返回当前对象的原始值(primitive value)。Number, Date, Boolean 对象会返回其原始值。比如:

new Number(10).valueOf() === 10  // true

作为 Object prototype 上的方法,它够低调的了。低调到用了都不知道。因为实际上,你几乎用不着去调用它,在需要的时候,会被自动调用。比如,进行比较操作,看下面的代码。

var obj = {
    v: 10,
    valueOf: function() {
        return this.v++;
    }
};

if (obj > 9) { // yes, compare obj with number 9
    alert(obj.valueOf()); // 11
}

拿对象与数字进行比较,结果竟然是 true,如果去掉 valueOf 的定义,什么事情都不会发生。

了解到这个之后,再看上面第一个代码,就会觉得有点画蛇添足了呢?

new Number(10) === 10  // false
new Number(10) > 9 // true

但是是不行的。在 === 的情况下,valueOf 是不会被隐含调用的。那么,现在来看下面这样的代码就很好理解了。是隐含调用 valueOf 在作怪 😛

var now = new Date();
alert( now < new Date(now.getTime() + 30) ); // true

在了解了 valueOf 低调的作风之后,心里有底了,也许有派得上用场的地方,不过,就算派上场了,也看不见。

好的,最后留一个奇怪的问题让大家伤伤脑筋吧

var now = new Date();
alert( now == new Date(now.getTime()) ); // false
alert( now.valueOf() == new Date(now.getTime()) ); // ?

后一个结果,现象是 chrome,safari 里面是 true, firefox,opera 和 IE 里都是 false。究竟是为什么呢?

PS: 在网络上可以搜索到的 valueOf 的中文文档,都是说对于Array来说,“数组的元素被转换为字符串,这些字符串由逗号分隔,连接在一起。其操作与 Array.toString 和 Array.join 方法相同。”,估计这是对于 JScript 的吧。如这里所说,所有浏览器测试下来都是返回数组对象本身。

参考链接:
valueOf on Mozilla Developer Center