从两个小例子看js中的隐式类型转换

废话很少说,咱们先来看第一个例子吧。
某天,我遇到了这样一个问题:给出变量a和b的定义,使下面三个语句的输出结果都为true。数组

console.log(a<b);
console.log(a==b);
console.log(a>b);

看到题目的我第一反应是懵逼的,还有这样的操做???而后一开始的思路是往各类神奇的值上面找,好比undefined,null,NaN,“”这样的值,天然是没有获得想要的结果了。
但事实上,真的存在。来看代码:函数

function A(){
    this.a = 1;
}

A.prototype = {
    toString: function(){
        return this.a += 2;
    }
}

var a = new A();
var b = 5;
console.log(a < b);
console.log(a == b);
console.log(a > b);

上面的代码不难理解:变量a是经过构造函数A建立的对象,变量b就是一个很简单的数值。一开始,由于a是经过构造函数A建立的对象,因此值为1.而后每一次在执行 console.log()的时候,会调用一次A的toString方法。因此,在第一个console.log()的时候,a的值变成了3,而b的值是5,因此a<btrue;第二个console.log()的时候,a的值变成了5,而b的值仍是5,因此a=btrue;第三个console.log()的时候,a的值变成了7,而b的值依旧是5,因此a>btrue
通过上面的分析,咱们彷佛打开了一个新世界的大门,这里涉及到一个比较重要的概念:隐式类型转换。在上面的例子里,a和b是两个彻底不同的类型,可是它们进行了比较,还得出告终果,这就说明有一个类型在比较的过程当中转换成了另外一个类型。
这里须要提到一些规范来帮助咱们更好的理解。
(小于大于的比较规则和相等是同样的。)
对于字符串和数字来讲,ES5规范11.9.3.4.5这样规定:this

(1)若是Type(x)是数字,Type(y)是字符串,则返回x == ToNumber(y)的结果
(2)若是Type(x)是字符串,Type(y)是数字,则返回ToNumber(x) == y的结果

对于其余类型和布尔类型的比较,规范11.9.3.6.7这样规定:prototype

(1)若是Type(x)是布尔类型,则返回ToNumber(x) == y的结果
(2)若是Type(y)是布尔类型,则返回x == ToNumber(y)的结果

对于null和undefined来讲,ES5规范11.9.3.2.3这样规定:code

(1)若是x为null,y为undefined,则结果为x == y
(2)若是x为undefined,y为null,则结果为x == y

也就是说,null和undefined是相等的。
对于对象和非对象来讲,ES5规范11.9.3.8.9这样规定:对象

(1)若是Type(x)是字符串或数字,Type(y)是对象,则返回x == ToPrimitive(y)的结果
(2)若是Type(x)是对象,Type(y)是字符串或数字,则返回ToPrimitive(x) == y的结果

基本就是上面这几种常见的类型的比较了。而后出现了一个咱们好像不太常见的东西:ToPrimitive()这个方法。咱们来简单了解一下:
对象(或者数组)再进行比较或者类型转换的时候,先会被转换为相应的基本类型值,而后再根据须要进行转换。再转换为基本类型值的时候,抽象操做ToPrimitive会先检查该值是否拥有valueOf()方法。若是有且返回基本类型值,就使用该值做为基本类型值,若是没有就使用toString()方法的返回值做为基本类型值。
上面例子中的相等操做咱们使用了==,而不是===。对于这两者的区别,咱们常常听到的是,==是不严格相等,只要值相等便可,而===是严格相等,必须值和类型都相等才能够。对于==来讲,类型不重要,也就是说在这个过程当中是包含了类型转换的。因此,在YouDontKnowJS这本书中,给出的正确解释是:字符串

==容许在相等比较总进行强制类型转换,而 ===不容许。

而后咱们再来看第二个例子吧
题目是这样的:[1]+[2]-[3]=?
此次打算先分析再给出答案,顺便你们也能够本身想一想结果是什么。
首先咱们看到加减运算符左右两边的值都是数组,那前面提到过对于数组的处理。由于数组的valueOf()操做没法获得简单的基本类型值,因此会调用toString(),这样的话上面那个式子就变成了"1"+"2"-"3"=?。如今这个式子相信你们都比较熟悉了,不过不知道会不会有人一时头脑发热,把答案想成了0。
而后咱们继续往下,由于是加减操做符,因此咱们从左至右开始计算,"1"+"2"这个结果究竟是3仍是12呢。那就记住简单的一句话:若是有一个值是字符串,那么就进行字符串拼接,不然进行数字加法。那么很明显,这里是2个字符串,进行字符串拼接,获得"12"
好了,到目前为止,式子已经变成了"12"-"3"了,这应该已经很明显了吧,字符串拼接是确定不可能的,那就是进行数字运算了,那就是最简单的12-3了,因此最终结果就是9。
其实这个例子里的经过加减运算符进行隐式类型转换在咱们平常代码中常常出现,只是可能你们没有特别关注,好比a + ""是把a转换为字符串;a - 0是把a转换为数字。it

相关文章
相关标签/搜索