# 类型间的转换

类型转换可以分为两种:

  • 隐式类型转换
  • 显式类型转换

在 JS 中只有 3 种类型的转换

  • 转化为 Number 类型:Number() / parseFloat() / parseInt()
  • 转化为 String 类型:String() / toString()
  • 转化为 Boolean 类型: Boolean()

# 转 boolean

其他类型转换为 boolean 转换结果只能为 true 或者 false。除了 0NaN空字符串nullundefinedfalse 转换的值是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-0NaNNaN

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

解析:

  1. 首先100 + true +连接符两边存在Number类型,true转number为1,进行加法运算,结果为:101
  2. 101 + 21.2 +连接符两边均为Number类型,进行加法运算,结果为:122.2
  3. 122.2 + null +连接符两边存在Number类型,null转number为0,进行加法运算,结果为:122.2
  4. 122.2 + undefined +连接符两边存在Number类型,undefined转number为NaN,NaN与任何数据类型计算都为NaN,结果为:NaN
  5. NaN + "Tencent" +连接符两边存在String类型,NaN转string为"NaN",进行字符串拼接,结果为:"NaNTencent"
  6. "NaNTencent" + [] +连接符两边存在String类型,[]转string为"",进行字符串拼接,结果为:"NaNTencent"
  7. "NaNTencent" + null +连接符两边存在String类型,null转string为"null",进行字符串拼接,结果为:"NaNTencentnull"
  8. "NaNTencentnull" + 9 +连接符存在String类型,9转string为"9",进行字符串拼接,结果为:"NaNTencentnull9"
  9. "NaNTencentnull9" + false +连接符存在String类型,false转string为"false",进行字符串拼接,结果为:"NaNTencentnull9false"

参考

通过大厂面试题研究JavaScript数据类型转换 (opens new window)