开始之前,先来回顾一下valueOf()的返回值
image.png
显示转换
显式类型转换主要是指通过String、Number、Boolean等构造方法转换相应的字符串、数字、布尔值
1.转换成字符串
image.png
对象类型,先将对象类型转换成基本类型
- 调用toString()方法,如果返回基本类型,就调用String()构造方法转换该值
- 如果toString()方法返回的不是基本类型,则再调用valueOf()方法,如果返回基本类型的值,则用String()构造方法转换该值。
- 如果valueOf()方法返回的也不是基本类型,就抛出错误
2.转换成数值
image.png
注意:
- 字符串转换成基本类型,是精确转换
- console.log(Number(' \t\n 3.23322\t '));//Number可以自动去掉两头空白符,输出3.23322
对象类型转换为数字,和上面对象转换为字符串类似,只是转为数字时是先调用valueOf()方法,再调用tostring()方法:
- 首先调用对象自身的valueOf()方法,如果返回基本类型的值,则用Number构造函数进行转换。
- 如果valueOf()返回的不是基本类型的值,则再调用toString()方法,如果返回基本类型的值,值用Number构造函数进行转换。
3.转换成布尔值
除了一下几种情况返回false,其他都返回true
null,0,-0,+0,NaN,undefined,空字符串
隐式转换
自动类型转换就是不需要人为强制的进行转换,js会自动将类型转换为需要的类型,所以该转换操作用户是感觉不到的,因此又称为隐性类型转换。自动类型转换实际上和强制类型转换一样,也是通过String()、Number()、Boolean()等构造函数进行转换,只是该操作是JS自己自动完成的而已。
坑点:
1.字符串连接符与算术运算符隐式转换规则混淆
当一边是字符串是,加号就是字符串连接符,会将其他数据类型调用String()转换成字符串然后拼接
1+'true'//1true String(1)+'true'='1true'
1+true //2 1+Number(true)=1+1=2
1+undefined //NaN 1+Number(undefined)=1+NaN=NaN
1+null //1 1+Number(null)=1+0=1
2.关系运算符:会把其他数据类型转换成number之后再比较关系
'2'>10 //false 当有一边是字符串时,会将它使用Number()转换,再比较 Number('2')>10=2>10 false
'2'>'10'//true 当两边都是字符串时,同时转换成number然后比较,字符挨个进行unicode编码的比较 '2'.charCodeAt()>'10'.charCodeAt()=50>49
'abc'>'b' //false 同理上面
NaN==NaN //false
undefined==null //true
3.复杂类型在进行隐式转换时,会先转成String,再转换成Number类型进行比较
image.png
[1,2]=='1,2' //true [1,2].valueOf()=>[1,2] [1,2].toString()=>'1,2'
Var a=?
if(a==1&&a==2&&a==3){
console.log(1);
}
如何完善a,使其正确打印1
解答:
复杂数据类型会先调用valueOf()方法,然后转换成number运算,可以重写对象的valueOf()方法
var a={
i:1,
valueOf:function(){
return a.i++
}
}
4.逻辑非隐式转换与关系运算符隐式转换搞混淆
[]==0 //true [].valueof()=[] => [].toString()='' =>Number('')=0
![]==0 //true 本质是![]逻辑非与0比较;逻辑非优先级高于关系运算符 Boolean([])=1 => !1=0
[]==![] //true 本质是空数组[]与![]这个逻辑非表达式结果进行比较 [].valueOf().toString()='' ![]=false Number('')==Number(false)
[]==[] //false 引用类型存储在最终,栈中存储的是地址,地址不同
{}==!{} //false 本质是对象{}与!{}的逻辑表达式结果进行比较 {}.valueOf().toString()='[object Object]' !{}=false Number('[object Object]')==Number('false') 结果是false
{}=={} //地址不同