在js中,类型转换是一个被很是多人诟病的地方。新手看了会发矇,老手看了会头疼。前端
类型转换,又成为强制类型转换,主要区分为显式强制类型转换和隐式强制类型转换面试
按我理解,类型转换的意思就很明显,就是当程序运行时须要此刻的变量的类型与变量的实际类型不符时,就会进行强制转换,在一些静态语言中,这个过程发生在编译阶段,或者干脆就抛出错误。而在js中,这个转换过程发生在运行时,因此你写代码的时候并不会意识到本身已经掉进坑里了。函数
而显式强制类型转换,简单的说,就是你以为你能够明面上一眼看出来的,好比‘’ + number
,+string
,Boolean(value)
; 而隐式强制类型转换就是反过来的意思。编码
举个栗子:code
var a = 'value'; if (a == true) { console.log('a is true'); } else if (a == false) { console.log('a is false'); }
按照正常的脑回路,通常人不会这么写。可是确实是有人会写if (a == true) {...}
这种语句,固然,后面的else if (a == false)
是为了节目效果加的。即使是这样,a == true
这种写法也是不可取的。对象
最后的输出是,两个都不输出。即在这个隐式强制类型转换中,a即不会等于true, 也不会等于false。开发
首先解释一下为何a既不等于true, 也不等于false。按照正常人类的脑回路,应该是将a先转换为布尔值,而后再将两个布尔值对比。这种状况下,a转成布尔值只能转换成true或者false。要是这么想,那你就是too young, too simple了字符串
当使用相等操做符==
进行判断时,将遵循如下规则(来自红宝书):string
· 若是又一个操做数是布尔值,则在比较相等性以前先将其转换为数值(false转换为0,而true转换为1
· 若是一个操做数是字符串,另外一个操做数是数值,在比较相等性以前先将字符串转换为数值
· 若是一个操做数是对象,另外一个操做数不是,则调用对象的valueOf()方法,用获得的基本类型值按照以前的规则进行比较
· null和undefined是相等的
· 要比较相等性以前,不能将null和undefined转换成其余任何值
· 若是一个操做数是NaN,则相等操做符返回false。
· 若是两个操做数都是对象,则比较它们是否是同一个对象,是则返回true,不然返回false
因此就能够知道上例中,转换是如何进行的。首先两个相等操做的操做数中都包含布尔值,先将布尔值转换为数值因此这里true转换为1,false转换为0。接下来再次进行比较,此时两对操做数中都包含一个字符串操做数,则将字符串转换为数值, a转换为数值是NaN,此时再次进行比较,因为有一个操做数是NaN,按照规则,返回false。因此a既不等于true也不等于false。console
由上能够看出,使用==
进行条件判断的时候是很是具备危险性的,尤为是当其中一个操做数为true的时候,若是另外一个操做数不为布尔值,则颇有可能就掉进坑里了。
那么通常在判断的时候怎么去进行判断比较好呢。我认为尽可能不使用==
操做符。使用===
进行全等判断,或者直接将你须要判断的值丢进if判断里,好比if (a == true)
能够改为if (a)
或者if (!!a)
这样就能避开==
操做符的坑了。若是必定要使用==
进行比较,不用不舒服,则最好先将操做数进行显式类型转换为同一类型的数据,再进行比较,
知其然就要知其因此然。
为何if (a)
和if (!!a)
就能够避开==
操做符的坑呢?它们进行强制类型转换时的转换规则又是怎样的。
其实在if的判断语句块内,若是判断值不是布尔值的话,会自动调用Boolean()函数进行布尔值的转换。而!!则至关于一次Boolean()的值类型转换了。因此在if的判断语句里直接放入判断条件和显式的将判断条件进行转换,其做用是同样的。区别也只是在因而否对后续看代码的人友好了,若是后面代码维护多是接触代码不深的新手,则建议进行显式的转换。
由上面的解释能够知道if (a)
和if (!!a)
,if (Boolean(a))
的做用是同样的,因此这里只要了解一下Boolean()函数的转换规则就能够了:
任何非空字符串为true,空字符串('')为false
任何非零数字值(包括无穷大)为true,0和NaN为false
任何对象为true,null为false
undefined为false
以上规则来自红宝书,部份内容省略
看以上的Boolean()函数的转换规则,与咱们平常工做中所须要的类型转换是很是契合的。
好比咱们广泛会认为并要求if能够拦截空字符串,false,null,undefined,0与NaN
须要注意的是,虽然红宝书上并没明确指出,但三元运算符( ? :
)使用的转换规则也是Boolean()函数的转换规则.
而除了条件判断,在其余一些操做里也会出现类型转换,好比关系操做符(<, >, <=, >=
):
var a = '23'; var b = '3'; console.log(a < b); // true
上面这个转换可能不少的前端开发工程师都掉进过坑里并摸不着头脑。
可能你也看出来了出现‘23’
小于‘3’
的缘由或许是在于它们都是字符串。若是关系操做符(<,>,<=,>=)两边都是字符串,则比较两个字符串对应的字符编码。'2'的字符编码是50,而3的字符编码是51,因此这里出现了‘23’小于‘3’的状况。
到这里不少人都会惊叹一声,并表示记住了此知识点。可是这样每每是不够的,你须要深挖下去,须要确切的了解关系操做符的转换规则,才能确保不会再次掉进它的坑里。
若是两个操做数都是数值,则执行数值比较 若是两个操做数都是字符串,则比较两个字符串对应的字符编码值
若是一个操做数是数值,则将另外一个操做数转换为一个数值,而后执行数值比较
若是一个操做数是对象,则调用这个对象的valueOf()方法,并用获得的结果根据前面的规则进行比较
若是一个操做数是布尔值,则先将其转换为数值,而后再执行比较
若是一个操做数是NaN,undefined,则返回false
若是操做数为null, '', 则转换为0进行比较
多看看红宝书就会发现js中的类型转换其实坑仍是不少的,还有一些加减乘除的操做符自己也会产生类型转换的问题。可是基本问题不是太大,因此就不单独拎出来了。
最后,一道思考题:
// do something ... console.log(typeof a); // 'object' console.log(a == false); // true
上面的对象为何会等于false,这个题是以前刷到的一道面试题,可不是我瞎编的。。
最后,欢迎斧正,没有仔细的准备,因此写的少且杂,也是做为本身的一个总结回顾吧。