toString()和valueOf()

617 阅读3分钟

哪些对象有valueOf()和toString()方法呢?

  • 需要明确的是,除了null和undefined,其他类型都自身有或继承有valueOf()和toString()方法;
  • Object.prototype.valueOf()返回指定对象的原始值;
  • Object.prototype.toString()返回一个表示该对象的字符串。
  • 这两种方法是Primitive抽象操作里经常会用到的;默认情况下,执行这个抽象操作会先执行valueOf方法,如果返回的不是原始值,会继续执行toString方法,如果返回的还不是原始值,那么会报错;如果有指定转换类型时,情况又会有所不用;
  • Array,Function,Math和Error对象自身没有valueOf方法,继承的是Object.prototype.valueOf()的原始方法,返回类型本身;如:
[].valueOf()//[]
function A(){};
A.valueOf();//function A(){}

(注意:valueOf和toString方法在Date,array等对象中有些是被重写过的,所以不同对象调用此方法可能产生的操作不同,如果没有会调用最原始的Object.prototype的valueOf和toString方法)

隐式转换

隐式转换的情况多发生与和某些操作符,如一元操作符,位操作符,加性,乘性操作符,相等操作符等时会进行隐式转换;并且针对这些操作符红宝书上都有明确的转换规则;

  • 相等操作符:
    • 如果有操作数是布尔值,则先转换为数值再进行比较;
    • 如果一个操作数是字符串,另一个操作数是数值,比较值钱先将字符串转换为数值;
    • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf方法,用得到的基本类型按照前面的规则进行比较;

valueOf和toString优先级

对象到字符串

一般来说,对象到字符串的转换经过了如下步骤: 1.如果对象具有toString()方法,则调用这个方法。如果它返回一个原始值,js将这个值转换成字符串,并返还这个字符串结果。 2.如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么js将调用valueOf()方法。 3.否则,js无法从toString()或者valueOf()获得一个原始值,因此这时它将抛出一个类型错误异常。

对象到数字

一般来说,对象到数字的转换过程中,js做了同样类似的事情,但这里它会首先尝试使用valueOf()方法: 1.如果对象具有valueOf()方法,后者返回一个原始值,则js将这个原始值转换成数字,并返回这个数字。 2.否则,如果对象具有toString()方法,后者返回一个原始值,则js将转换并返回。 (首先js转换成相应的字符串原始值,再继续将这个原始值转换成相应的数字类型,再返回数字) 3.否则,js抛出一个类型错误异常。

JS核心内置类

对象通过toString或valueOf方法转换为原始值,JS语言核心的内置类会首先调用valueOf(),再尝试使用toString()。对于所有非日期对象来说,对象到原始值的转换基本上是对象到数字的转换

valueOf和toString重写的情况

如果对象只重写了toString,对象转换时会无视valueOf的存在来进行转换;但是,如果只重写了valueOf方法,在要转换为字符串使会优先考虑valueOf方法。

小试身手

  • 经典题:[]==![]
  • 解题: 根据相等操作符第一条,先把![],转换为0;然后,相等操作符第三条将[]调用valueOf,但是返回值不是原始值,再调用toString方法,返回“”空字符串,再相等操作符第二条,将空字符串转为数值,为0;因此,最终的结果为true。