# 类型间的转换
类型转换可以分为两种:
- 隐式类型转换
- 显式类型转换
在 JS 中只有 3 种类型的转换
- 转化为 Number 类型:Number() / parseFloat() / parseInt()
- 转化为 String 类型:String() / toString()
- 转化为 Boolean 类型: Boolean()
# 转 boolean
其他类型转换为 boolean 转换结果只能为 true 或者 false。除了 0、NaN、空字符串、null、undefined、false 转换的值是false,其余都是true。
下面列举了一些转换规则:
| 原始值 | 转换目标 | 结果 |
|---|---|---|
| number | 布尔值 | 除了0、NaN都为true |
| string | 布尔值 | 除了空字符串,其他字符串都转化为true |
| undefined、null | 布尔值 | false |
| 引用类型 | 布尔值 | true |
# 转换为字符串
| 原始值 | 转换目标 | 结果 |
|---|---|---|
| number | 字符串 | 举例:1->'1' |
| Boolean、函数、Symbol | 字符串 | 'true' |
| 数组 | 字符串 | [1, 2] -> '1,2' |
| 对象 | 字符串 | '[object Object]' |
举例:
1 + '' // '1'
false + '' // 'false'
{} + '' // '[object Object]'
// Symbol() + ''
null + '' // 'null'
undefined + '' // 'undefined'
function fn(){} + '' // 0
'' + function fn(){} // 'function fn(){}'
{} + '' // 0
# 转换为数字
| 原始值 | 转换目标 | 结果 |
|---|---|---|
| string | 数字 | '1' -> 1,'hello' -> NaN |
| 数组 | 数字 | 空数组转为为0;数组中只有一个元素,且这个元素为数字,转换为数字,其他情况为NaN |
| null | 数字 | 0 |
| 除了数组的引用类型 | 数字 | NaN |
| Symbol | 数字 | 报错 |
举例:
Number('1') // 1
Number('1a') // NaN
Number(false) // 0
Number(true) // 1
Number({}) // NaN
Number([1]) // 1
Number([1, 2]) // NaN
Number(Symbol) // NaN
Number(Symbol()) // Cannot convert a Symbol value to a number
Number(function fn(){}) // NaN
Number(null) // 0
Number(undefined) // NaN
对象转换为数字:
- 先调用对象的
Symbol.toPrimitive这个方法,如果不存在这个方法 - 再调用对象的
valueOf获取原始值,如果获取的值不是原始值 - 再调用对象的
toString把其变为字符串 - 最后再把字符串基于
Number()方法转换为数字
# 操作符 ==
- 两边的类型是否相同,相同的话就比较值的大小,例如1==2,返回false
- 判断的是否是null和undefined,是的话就返回true
- 判断的类型是否是String和Number,是的话,把String类型转换成Number,再进行比较
- 判断其中一方是否是Boolean,是的话就把Boolean转换成Number,再进行比较
- 如果其中一方为Object,且另一方为String、Number或者Symbol,会将Object转换成字符串,再进行比较
上面我们提到了操作符 == ,在我们编程的过程中还会使用到 ===。它们两个之间有什么区别呢?
==运算符两边的值类型不同的时候,存在隐式类型转换,===运算符两边值不相同的时候不存在类型转换。===运算符是严格相等,左右两边的值不但值要相等,类型也要相等。
提到了 === 操作符,大家可能会想到 Object.is() 那它们两个有什么区别呢?
Object在严格等于的基础上修复了一些特殊情况下的失误,具体来说就是 +0 和 -0,NaN 和 NaN。
function is(x, y) {
if (x === y) {
// 1/+0 = +Infinity, 1/-0 = -Infinity
return x !== 0 || y !== 0 || 1 / x === 1 / y
}else {
return x !==x && y !== y
}
}
# 类型转换真题
题一:
{} + [] == 0 // 正确
解析: 对于编译器而言,代码块不会返回任何的值接着+[]就变成了一个强制转number的过程,[]通过oPrimitive变成'',最后''通过ToNumber操作转换成0
题二:
[] + {} == 0 // [] + {} == '[object Object]'
解析:[] 转化为 '' , {} 转为 '[object Object]'
题三:
[] == ![] // true
解析:![]的结果为false,false会转换为0;[]转换为数字0,也就变成了0 == 0,所以返回true
题四:
let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
// NaNTencentnull9false
解析:
- 首先100 + true +连接符两边存在Number类型,true转number为1,进行加法运算,结果为:101
- 101 + 21.2 +连接符两边均为Number类型,进行加法运算,结果为:122.2
- 122.2 + null +连接符两边存在Number类型,null转number为0,进行加法运算,结果为:122.2
- 122.2 + undefined +连接符两边存在Number类型,undefined转number为NaN,NaN与任何数据类型计算都为NaN,结果为:NaN
- NaN + "Tencent" +连接符两边存在String类型,NaN转string为"NaN",进行字符串拼接,结果为:"NaNTencent"
- "NaNTencent" + [] +连接符两边存在String类型,[]转string为"",进行字符串拼接,结果为:"NaNTencent"
- "NaNTencent" + null +连接符两边存在String类型,null转string为"null",进行字符串拼接,结果为:"NaNTencentnull"
- "NaNTencentnull" + 9 +连接符存在String类型,9转string为"9",进行字符串拼接,结果为:"NaNTencentnull9"
- "NaNTencentnull9" + false +连接符存在String类型,false转string为"false",进行字符串拼接,结果为:"NaNTencentnull9false"
参考