七种数据类型

JS 中共有七种数据类型

  • null
  • undefined
  • boolean
  • number
  • string
  • symbol
  • object

除了 object,所有的数据类型都被称为“原始数据类型”

JS 中每个变量都保存了一个值,每个值都对应着一种数据类型

在使用过程中,值的数据类型会发生相应的变化,以促使代码正常运行

显示转换

Number()

typeof new Number('a') // "object"
typeof Number('a') // "number"

给 Number() 函数传递任何参数,都会返回一个 number 类型的值

Number() 在转换原始数据类型时

Number(324) // 324
// 数值类型,直接返回
Number('324') // 324
// 字符串可以转成数字,就将其转成数字返回
Number('324abc') // NaN
// 字符串不可转成数字,返回 NaN
Number('') // 0
// 空字符串,返回 0
Number(true) // 1
// true,返回 1
Number(false) // 0
// false,返回 0
Number(undefined) // NaN
// undefined,返回 NaN
Number(null) // 0
// null,返回 0

值得一提的是 parseInt() 也可以将参数转化为数值

parseInt('324abc') // 123
parseInt('abc324') // NaN
parseInt('') // NaN
parseInt(true) // NaN
parseInt(false) // NaN
parseInt(undefined) // NaN
parseInt(null) // NaN

Number() 在转换对象时

伪代码如下

Number(obj)
if(Type obj.valueOf() is Primitive) return Number(obj.valueOf())
else(Type obj.toString() is Primitive) return Number(obj.toString())
else TypeError
let obj = {
    valueOf(){
        return 110
    },
    toString(){
        return 120
    }
}
Number(obj) // 110

let obj2 = {
    valueOf(){
        return []
    },
    toString(){
        return 120
    }
}
Number(obj2) // 120

Number([])

  1. [].valueOf() 返回 [],非原始数据类型
  2. [].toString() 返回 "",为原始数据类型,空字符串
  3. Number('') 返回 0

Number({})

  1. ({}).valueOf() 返回 {},非原始数据类型
  2. ({}).toString() 返回 "[object object]",为原始数据类型,字符串
  3. Number("[object object]"),字符串不可转换为数值,返回 NaN

String()

typeof new String(123) // "object"
typeof String(123) // "string"

给 String() 函数传递任何参数,都会返回一个 string 类型的值

String() 在转换原始数据类型时

String('abc') // "abc"
// 字符串类型直接返回
String(123) // "123"
// 数值类型转换为相应的字符串
String(true) // "true"
String(false) // "false"
String(undefined) // "undefined"
String(null) // "null"

String() 在转换对象时

其转换原理与 Number() 转换对象的原理类似,只不过 Number() 先调用对象的 valueOf() 方法进行判断,失败后,再调用对象的 toString() 方法。String() 则是先调用对象的 toString() 方法进行判断,失败后,再调用对象的 valueOf() 方法

let obj = {
    valueOf(){
        return '110'
    },
    toString(){
        return '120'
    }
}
String(obj) // "120"

let obj2 = {
    valueOf(){
        return "120"
    },
    toString(){
        return {}
    }
}
String(obj2) // "120"
String([]) // ""
String({}) // "[object Object]"

Boolean()

typeof new Boolean(123) // "object"
typeof Boolean(123) // boolean

Boolean() 返回 false 的情况很少

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(+0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean('') // false

除此之外,皆为 true

Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

隐式转换

自动转换为boolean

JS 遇到预期为 boolean 时,会内部调用 Boolean()

  • if (conditions) => if (Boolean(conditions))
  • while (conditions) => while (Boolean(conditions))
  • expr1 && expr2 => Boolean(expr1) && Boolean(expr2)
  • expr1 || expr2 => Boolean(expr1) || Boolean(expr2)
  • ! expr1 => ! Boolean(expr1)
  • condition ? value1 : value2 => Boolean(condition) ? value1 : value2

自动转换为string

在字符串的加法运算时, a + b,若 a 为字符串,b 不为字符串,则发生 a + String(b)

'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
let obj2 = {
    valueOf(){
        return "120"
    },
    toString(){
        return {}
    }
}
'5' + obj2 // 5120
let obj = {
    width: 100
}
'5' + obj.width // 5100

自动转换为number

在使用算术运算符时,会调用 Number(),使算子都变成 number

算术运算符有

  • +(加)
  • -(减)
  • *(乘)
  • /(除)
  • %(取余)
  • ++
  • --
  • -(一元负值符)
  • +(一元正值符)
  • **(指数运算)
'5' - '2' // 3
'5' * '2' // 10
true - 1  // 0
false - 1 // -1
'1' - 1   // 0
'5' * []    // 0
false / '5' // 0
'abc' - 1   // NaN
null + 1 // 1
undefined + 1 // NaN
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0

当 + 以二元运算符使用,且算子中有一个为字符串时,当作拼接字符串使用

当 + 以二元运算符使用,且算子中有一个为对象时,当作拼接字符串使用

[1,2] + [2,3] // "1,22,3"
[] + {} // "[object object]"
{} + [] // 0
// {} 被当作块级作用域处理
// + 被当作一元运算符
// 调用 Number([])
({}) + [] // "[object object]"

详解两类隐式转换

x == y

  1. 如果 x,y 的类型相同,则返回 x == y
  2. 如果 x 为 undefined,y 为 null,或者, x 为 null,y 为 undefined,都返回 true
  3. 如果 x,y 都为基础数据类型,但类型不同,返回 Number(x) == Number(y)
  4. 如果一者为基础数据类型,一者为对象,则返回 ToPrimitive(obj) == primitive

ToPrimitive(obj),先调用 obj.valueOf(),判断是否是基础数据类型,若不是,则调用 obj.toString()

[] == ![] => [] == !Boolean([]) => [] == !true => [] == false => "" == false => true

console.log(([][[]]+[])[+!![]]+([]+{})[!+[]+!![]])

1.([][[]]+[])

([][[]]+[]) => ([][""]+[]) => (undefined + []) => ("undefined")

2.[+!![]]

[+!![]] => [+!!Boolean([])] => [+!!true] => [+true] => [+1] => [1]

那么 ([][[]]+[])[+!![]] => ("undefined")[1] => "n"

3.([]+{})

([]+{}) => ("[object object]")

4.[!+[]+!![]]

[!+[]+!![]] => [!+[]+true] => [!+"" + true] => [!+0+true] => [!0+true] => [1+true] => [2]

那么 ([]+{})[!+[]+!![]] => ("[object object]")[2] => "b"

综上

console.log(([][[]]+[])[+!![]]+([]+{})[!+[]+!![]]) // nb

参考资料


nbb3210
436 声望31 粉丝

优雅地使用JavaScript解决问题