在未彻底搞清楚js隐式类型转换之前。咱们先看看这几道题: 请说出他们的输出结果:
1 console.log(+true)
2 console.log([]==false)
3 console.log(![]==false)
4 console.log({}==false)
5 console.log({}==false)
6 let res=100+ture+21.2+null+undefined+"sean"+[]+null+9+false
console.log(res)
如果对js的隐式类型转换规则不了解。这6道题很容易就挂掉。
下面我们一步步抽丝剥茧分析下这6道题过程中到底发生了什么:
题目一:
console.log(+true)
对于 + 而言,它比较特殊。一般用作数学运算,但是一旦它的两边任意一边出现了对象或者字符串,那么+就变成了字符串拼接。 观察 coonsole(+true),+右边的true并非字符串也并非对象,所以此时+应该是数学运算。既然是数学运算,此时就需要把true变成数字,true==》数字,最后的结果就是1 ,也就是coonsole(+true)变成了 coonsole(+1)==》输出1
console.log(+true)
+true过程:
(1)true--->Numer // =1
(2)+1 -->Number //1
题目二
console.log([]==false) 在两个不同类型数据类型进行==比较时,有这样几个规则:
1 null==undefined:true,但是===结果是false,(因为类型不一样)
2 字符串==对象,需要把对象转换为字符串
3 剩下如果==两边数据类型不一样,都是需要转为数字再进行比较
[]和false数据类型不同,需要两边都转化为数字再进行比较,false---》数字为0,而[]属于对象类型,对象类型转为数字的过程是先转为字符串再转化为数字。而[]===》字符串是空字符串----》数字结果为0。最后结果成了console.log(0==0),所以最后结果是true
console.log([]==false)过程
(1) []--->Number ([])----->String(="")------> Number(=0) (对象类型转为数字的过程是先转为字符串再转化为数字)
false--->Number // 0
(2) console.log(0==0) (经过第一轮转化两边都是0)
(3) 结果为true
题目三:
console.log(![]==false) 这题不一样的在于 ![]的优先级要高于==。所以console.log(![]==false)要先进行![]运算,最后再进行==比较。根据上面的规则。![]--->布尔值,[]因为不在0 ,NaN , null ,undefined 和空字符串这五个值中,所以它应该是true,而!ture就变成了false,所以console.log(![]==false)--》变成了console.log(false==false),所以最后的结果还是true
console.log(![]==false)过程
(1) ![]先做运算变成布尔值 , ![]----->Boolean // []先变成true, 再取反成false,
(2) console.log(false==false) (经过第一步的转化成了)
(3) 结果为true
题目四:
console.log({}==false) 有了上面一道题的基础。这个题就好理解了: {}和false类型不一样。所以他们需要转为数字再进行比较。false--》数字=0;而{}---》数字则需要先调用其toString()转化为字符串再转化为数字,也即是对象--》字符串--》数字,而{}在调用toString方法的时候就有点尴尬了。对象本身的toString()方法是用来判断数据类型的。所以 console.log({}.toString())===>结果成了"[object,object]",那 '[object,object]'----》数字自然就变成了NaN,所以最后结果就成了NaN==0,而我们知道NaN和任何值都不相等。所以最终结果就是false
console.log({}==false)过程
(1) {}----->Number ({}--- 调用toString()------>Strng (结果是"[object,object]")---调用Number()-- Number('[object,object]')----->Number ) //结果为NaN
false--->Number // 结果为0
类型不一样,需要都转化为数字进行比较
(2) console.log(NaN==0) //结果为false,NaN和任何值都不相等
(3) 结果为false
题目五
console.log(!{}==false) 同样的道理,因为因为!比==优先级要高,所以!{}要先进行运算。也就是把!{}转化为布尔值,{}不在0,NaN , null ,undefined 和空字符串这五个值中,所以它应该是true,!{}结果是false,等号左边是false,再和右边的false进行比较。结果肯定是true
console.log(!{}==false)过程:
(1) !{}先做运算。 !{}------>Boolean {}--先转化为---->true,再取反,变成false
(2) console.log(false==false) //进过上一步转化左右两边变成console.log(false==false)
(3) 结果为true
题目六
let res=100+ture+21.2+null+undefined+"sean"+[]+null+9+false 从左到右开始,100+true,因为+左右变量既没有字符串也没有对象,所以此时+是数学运算。既然是数学运算。肯定需要把左右两边都转化为数字。true-->数字为1,所以100+true=101,同理+21.2=121.2 ,继续+null,把null转为数字为0,还是121.2,继续+undefined(任何数+undefined最终结果都是NaN),所以到这里就成了NaN,再继续+"sean",因为+后面出现了字符串,所以此时结果是"NaNsean",+null后因为此时"NaNsean是字符串,所以变成了字符串拼接,NaNsean+[]=NaNsean,继续往后,因为前面的NaNsean是字符串。所以后面整个都变成了字符串拼接。 最后的结果就成了字符串拼接,NaNseannull9false
100+ture+21.2+null+undefined+"sean"+[]+null+9+false过程
(1) 100+ture=100+1 (+左右两边没有字符串也没有对象,此时+是数学运算)
(2) 100+ture+21.2=121.2 (+左右两边没有字符串也没有对象,此时+是数学运算)
(3) 100+ture+21.2+null=121.2 (+左右两边没有字符串也没有对象,此时+是数学运算)
(4) 100+ture+21.2+null+undefined=NaN (任何数和undefined相加都是NaN)
(5) 100+ture+21.2+null+undefined+"sean"=NaNsean (+右边出现字符串变成字符串拼接)
(6) 100+ture+21.2+null+undefined+"sean"+[]=NaNsean (+左边是字符串所以是字符串拼接)
(7) 100+ture+21.2+null+undefined+"sean"+[]+null=NaNseannull (+左边是字符串所以是字符串拼接)
(8) 100+ture+21.2+null+undefined+"sean"+[]+null+9=NaNseannull9 (+左边是字符串所以是字符串拼接)
(9)100+ture+21.2+null+undefined+"sean"+[]+null+9+false==NaNseannull9false (+左边是字符串所以是字符串拼接)
其他类型转为Number类型:**
1 显示转化:(特定需要转化为Number的)
Number(val),只要出现一个非数字的
ParsetInt、parseFloat()
2 隐式转换
isNaN (val) 数学运算,(特殊情况,+在出现字符串的情况下不是数学运算,是字符串拼接) 在==比较的时候,有些只需要转为数字再进行比较
其他类型转化为字符串的规则
1 显示转化
toString()
String()
2 隐式转化
一般是调用其toString() 加号运算的时候,如果某一边出现字符串则变成字符串拼接
把对象转化为数字,需要先toString()转为字符串再去转为数字
字符串转数字的过程中,只要出现一个非有效数字,全部转化为NaN
其他类型转化为布尔规则
1 基于以下方式可以把其他数据类型转为布尔
!转为布尔值后取反
!! 转化为 布尔值类型
Boolean(val)
2 隐式转换
只有 0 ,NaN , null ,undefined 和空字符串五个值变成布尔值为false,其他全部是true
** 隐式类型转换规则**
类型一样的几个特殊点:
{}=={} ---false,对象比较的是堆内存的地址
[]==[] ---false
NaN==NaN ---false (nan和任何数据都不相等)
类型不一样的转换规则
1 null==undefined:true,但是===结果是false,(因为类型不一样)
2 字符串==对象,需要把对象转换为字符串
3 剩下如果==两边数据类型不一样,都是需要转为数字再进行比较