JS隐式类型转换

161 阅读2分钟

1. 数据类型转换规则

介绍 ToString \ ToNumber \ ToBoolean \ ToPrimitive

1.1 ToString

规则如下:

  • null: => 'null'
  • undefined => 'undefined'
  • boolean: true => 'true' , false => 'false'
  • number: 遵循通用规则,1 => '1', NaN => 'NaN', 1e21 => '1e+21'
  • 普通对象:相当于使用 Object.prototype.toString(), {} => '[object Object]'
  • array: 相当于使用 Array.prototype.join(), 使用','连接,其中undefined、null处理为空字符串
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
String(1) // '1'
String(NaN) // 'NaN'
String(1e21) // '1e+21'
String({}) // '[object Object]'
String([]) // ''
String([1,undefined, 2, undefined, 3]) // '1,,2,,3'

1.2 ToNumber

  • null: null => 0
  • undefined: undefined => NaN
  • string:
    • 空字符串:0
    • 数字字符串:正常转换
    • 其他:NaN
  • boolean:
    • true => 1
    • false => 0
  • object: 先调用ToPrimitive转换为原始类型,再转换为数字
Number(null) // 0
Number(undefined) // NaN
Number('') // 0
Number('1') // 1
Number('a') // NaN
Number(true) // 1
Number(false) // 0
Number({}) // NaN
Number([]) // 0
Number([1]) // 1
Number([1,2]) // NaN

1.3 ToBoolean

falsy值转换为为false,其他为true

falsy值:false / undefined / null / 0 / '' / NaN

1.4 ToPrimitive

将对象类型转换为原始类型

重点:valueOftoString

  1. 先调用对象的valueOf方法,若valueOf方法返回原始类型的值,则结束
  2. 若无valueOf或返回的值非原始类型,则调用toString方法,按对象的ToString规则进行转换
  3. 若以上两种方法均不返回原始类型的值,则报错

特殊的,Date对象会先调用toString

const obj1 = {
    valueOf () {
      return 1
    },
    toString () {
      return 2
    }
}

Number(obj1) // 1

const obj2 = {
    valueOf () {
      return {}
    },
    toString () {
      return 2
    }
}
Number(obj2) // 2

const obj3 = {
    toString () {
      return 2
    }
}
Number(obj3) // 3

const obj4 = {
    toString () {
      return {}
    }
}
Number(obj4) // Uncaught TypeError: Cannot convert object to primitive value
Number([]) // 0
Number(['10']) // 10

ToNumber会先调用对象的ToPrimitive,再调用ToNumber

  • Number([]):
    • 数组先调用valueOf,返回自身,
    • 再调用ToString,String([])='',
    • 再调用ToNumber,Number('')=0
  • Number([10]):
    • 数组先调用valueOf,返回自身,
    • 再调用ToString,String([10])='10',
    • 再调用ToNumber,Number('10')=10

2. == 隐式转换

  • 有boolean =》 将boolean转换为number
  • 有string 且 有number =》 string转为number
  • 有对象 且 另一个非对象 =》 对象调用valueOf转换为原始类型,再根据前面的规则进行比较

2.1 存在boolean,boolean转number

false == 0 // true
true == 1 // true
true == 2 // false
  • true == 2:
    • boolean先转换为number:Number(true) = 1
    • 1 != 2 => false

2.2 string与number作比较,string转number

0 == '' // true
1 == '1' // true
1e21 == '1e21' // true
Infinity == 'Infinity' // true
true == '1' // true
false == '0' // true
false == '' // true

2.3 对象与非对象作比较,对象ToPrimitive

ToPrimitive: 先valueOf,不行再toString

'[object Object]' == {} // true
'1,2,3' == [1, 2, 3] // true
[2] == 2 // true
[null] == 0 // true
[undefined] == 0 // true
[] == 0 // true
  • [2]先valueOf,结果为自身,再toString,结果为‘2’,string转换为number,结果为2
  • [null] toString结果为空字符串,转换为number,结果为0
  • [undefined][0]同上

2.4 特别的

  • null 和 undefined 相等
  • null 和 undefined 不会转换为其他类型
  • 出现NaN,== 结果必为 false,NaN和NaN也不相等
  • 比较的对象都为对象,则需判断两者是否指向同一个对象,是则为true