今天发现一个神奇的现象,效果如下:
date
是一个对象,但是把这个对象和一个字符串相加的时候,却能得到日期字符串;把这个对象和数字相减,却能得到时间戳(毫秒数);也就是date
与字符串、数字进行运算时,会转成对应的类型。
其实造成以上现象的本质原因是:js
为了让两种不同类型的值进行运算或比较,会在运算前对他们进行转换,其实就是通过调用他们的toString()
或者是valueOf()
来得到转换后的值,然后再对转换后的值进行运算或者比较。
我们可以看一下,常用的几种数据类型的valueOf()
的返回值是什么。
1.数组
数组的
valueOf
返回的是一个对象,也是原对象本身。
2.Date
Date
的valueOf
的返回值是时间的毫秒数。
3.Number
Number
的valueOf
返回的是对应的number
类型的值。
4.Boolean
Boolean
的valueOf
返回的是一个boolean
类型的值。
5.Object
Object
的valueOf
返回的是一个Object
对象。也是原对象本身。
6.Function
Function
的valueOf
返回的是一个Function
对象。也是原对象本身。
总结如下:
- 包装类型的
valueOf()
会返回对应的基本类型的值;比如:Number
; -
Date
对象的valueOf()
返回对应的时间戳,也就是数字; - 其他类型的
valueOf()
,返回的是对象本身;
但是我们也可以通过自定义valueOf
方法来覆盖默认的行为,如下:
在未自定义
valueOf
之前,obj+"--name"
。返回的是[object object]--name
,自定义以后,obj+"--name"
返回'gby--name',这证明了,我们成功覆盖了原来的valueOf()
。
此时想到之前有遇到过,js 会在某些时候调用toString()
方法,那什么时候调用valueOf()
,什么时候调用toString()
,我们可以测试一下:
当valueOf()
和toString()
同时存在时,会优先调用valueOf()
;那如果valueOf
返回一个非基本类型时,会是什么结果,测试如下:
当自定义
valueOf
返回一个非基本类型 的数据时,会先调用valueOf()
,之后再调toString()
。
如果valueOf()
和toString
都返回对象,则会报错:
总结
js
为了让两种不同类型的值进行运算或比较,会在运算前对他们进行转换,其实就是通过调用他们的toString()
或者是valueOf()
来得到转换后的值,然后再对转换后的值进行运算或者比较。
valueOf()
和toString()
具体的调用机制如下:
- 调用
valueOf()
获得返回值,如果该返回值是基本类型,则会把该返回值作为最终值,并参与运算; - 如果上一步中
vulueOf()
返回的是非基本类型的值,则会进一步调用toString()
方法,获得toString()
的返回值,如果该返回值是基本类型,则会把该返回值作为最终值,并参与运算; - 如果上一步中
toString()
返回的是非基本类型的值,则会报如下错误: