基本数据类型:Number String Boolean Null Undefined
引用数据类型:Object(Function Array ...)
强制转换:
1. 其他类型转字符串:
(1) toString()
null和undefined这两个值没有toString()方法,会报错。
(2) String()
对于Number和Boolean实际上就是调用的toString()方法,但是对于null和undefined,就不会调用toString()方法, 它会将 null 直接转换为 "null", 将 undefined 直接转换为 "undefined"。
(3) +
任何数据和 + 连接到一起都会转换为字符串, 其内部实现原理和String()函数一样。
2. 其他类型转数字:
(1) Number()
对于字符串:
a. 如果是纯数字的字符串,则直接将其转换为数字
b. 如果字符串中有非数字的内容,则转换为NaN
c. 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0
对于布尔值:true 转成 1, false 转成 0
对于null:0
对于undefined:NaN
(2) parseInt() parseFloat()
parseFloat识别第一个小数点。
这两个方法专门用来处理字符串,对于非字符串会转为字符串。
如果第一个字符不是数字或者符号就返回NaN,空字符串返回NaN。
3. 其他类型转布尔值
Boolean()
0,NaN,null,undefined,"" --------> false,其他为true
引用类型为true
隐式转换:
问题引出:[] == false // true
咦~ 不是说对于引用类型转成布尔值应该为true吗?为什么这里是false?
是的,对于空数组我们调用Boolean([]) -> true,然而对于这里的比较运算,我们并没有调用Boolean方法,而隐式转换是存在于基本数据类型之间,因此这里的原理应该是:对于引用类型,先调用toString()方法转为字符串 [].toString() -> "",然后再将""转换为数字 Number("") -> 0, 而右边false转为数字也是0,故 [] == false。
那么我们是不是可以认为对于比较运算,都是先想办法转成数字再比较呢?接下来我们就来验证一下:
[1] == true // true [12] == true // false [12] == 12 // true
[1,2] == true // false [1,2] == false // false 这里[1,2].toString()->"1,2",Number("1,2")->NaN,NaN既不为1也不为0
{} == true // false {} == false // false 这里{}.toString()->Number([Object object])->NaN
null == true // false null == false // false 这里Number(null)->NaN 同理undefined
以上好像都没有什么问题,接着我们把右边的类型换一下:
[1,2] == "1,2" // true
如果按照转成数字的逻辑,左右两边应该都是NaN,而NaN == NaN // false,看来对于对象与字符串作比较,它省了一步,并没有都转成数字类型再进行比较。其实也比较好理解,因为对象本来就调用了toString(),就没有必要再转成数字了。
接下来,我们就可以进行总结了,其实对于比较运算,隐式转换的原理如下图所示:
除了对象与字符串作比较,其他的都会默认最终转为数字再进行比较。但是这里还有一个例外,那就是null == undefined // true。
补充:![] == false // true
这里涉及到运算符的优先级,先运算![] -> false,因为Boolean([]) -> true,故相等。