ECMAScript
数据类型包含简单数据类型(也称为原始类型)和复杂数据类型(对象)。其中简单数据类型包括:Undefined, Null, Boolean, Number, String, Symbol, BigInt(后面两个是ES6 新增)
,复杂数据类型包括:Object
。
typeof 操作符
typeof
操作符可以查看数据的类型,但有些可能不符合预期,例如null
和 function
typeof undefined // "undefined"
typeof null // "object" 注意,类型不是显示的'null',而是'object'
typeof true // "boolean"
typeof 12345 // "number"
typeof '字符串' // "string"
typeof Symbol(123) // "symbol"
typeof 234n //"bigint"
let obj = {}
let array = []
function fn() {}
typeof obj // "object"
typeof array // "object"
typeof fn // "function" 注意,函数也是对象的一种
//fn instanceof Object // true
typeof
不是函数而是操作符,所以不需要传参(但可以使用参数)
let message = "some string";
//当做操作符使用
console.log(typeof message); // "string"
//当做函数使用
console.log(typeof(message)); // "string"
Undefined 类型
Undefined
类型只有一个值,"undefined"
,当使用var
或者let
声明一个未初始化的变量时,其默认值就是undefined
let msg
console.log(msg == undefined) //true
怪异行为
当使用typeof
操作符检测一个未声明的变量时,仍然会返回undefined
let msg
//let age //确保没有声明 age
typeof msg // "undefined"
typeof age // "undefined"
Null 类型
Null
类型同样只有一个值null
。逻辑上讲,null
表示的是一个空对象,这也是给typeof
传一个null
会返回"object"
的原因。其实也可以说是一个bug
,根据*<<你不知道的JavaScript上卷>>103页*所说,根本原因如下
原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判 断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。
undefined
值是由null
值派生而来,因此用==
操作符,两者始终返回true
(发生类型转换)
console.log(undefined == null) //true
Boolean 类型
Boolean
类型有两个值true
和false
。
转换为false
的值有
false
Boolean("")
Boolean(0) //包括+0, -0
Boolean(+0)
Boolean(-0)
Boolean(NaN)
Boolean(null)
Boolean(undefined) //这也是为什么undefined == null 为true的原因,当使用==操作符会发生类型转换
除此之外的值都为true
一种快速转换为布尔值的方式
!!123
,两次取反
Number 类型
Number
类型使用IEEE 754格式表示数值和浮点值,因此会有
0.1 + 0.2 == 0.3 // false
八进制和十六进制
let octalNum1 = 077 // 表示八进制的63
let octalNum2 = 079 // 无效的八进制,当成79处理
//严格模式下,前缀0会被视为语法错误
let hexNum1 = 0xA //表示十进制10
浮点数
浮点数值中包含小数点,并且小数点后至少有一个数字
//以下都是合法的
let a = 1.1
let b = 0.1
let c = .1
//以下都会被转换成整数
let d = 10.0
let e = 10.
值的范围
ECMAScript
可以表示的最小数值为Number.MIN_VALUE
(这个值在浏览器中为5e-324
),最大数值为Number.MAX_VALUE
(这个值在浏览器中为1.7976931348623157e+308
),如果超过这个范围将会被自动转换为Infinity
和-Infinity
,可以使用Number.isFinite()
判断传入参数是否为有穷数
Number.isFinite(1111) //true
Number.isFinite(Infinity) //false
Number.isFinite(-Infinity) //false
Number.isFinite(Infinity - 1111) //false
Number.isFinite(-Infinity + 1111) //false
//用Infinity进行运算,结果仍然是Infinity
除此之外,还新增加了Number.MAX_SAFE_INTEGER (9007199254740991)
和 Number.MIN_SAFE_INTEGER(-9007199254740991)
可以使用Number.isInteger()
进行判断。
Number.isInteger(25) // true
Number.isInteger(25.1) // false
Number.isInteger(25.0) // true
Number.isInteger(5E-324) // false
Number.isInteger(5E-325) // true
Number.isInteger(3.0000000000000002) // true 由于采用的IEEE 754标准,超出了精度范围(53个二进制位,其中一个隐藏位和52个有效位)
NaN
NaN
,即'Not a Number'
不是一个数值
console.log(0 / 0) //NaN
//注意 NaN == NaN 是false
可以使用Number.isNaN()
判断一个值是否为NaN
Number.isNaN(NaN) //true
Number.isNaN(11) //false
Number.isNaN('10') //false //先转换成数值10,再判断
Number.isNaN('blue') //true
Number.isNaN(true) //false //转换成数值1
数值转换
有3个函数可以实现数值转换:Number(), parseInt(), parseFloat()
。Number()
是 转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。
Number()
- 布尔值,
true
转换为1
,false
转换为0
- 数值,直接返回
undefined
,返回NaN
null
,转换成0
- 字符串
- 如果是空字符串,返回
0
- 如果字符串包含数值字符(包括数值字符前的加、减号或有效的浮点值),则直接转换为一个十进制数值
- 如果字符串包含有效的十六进制格式如
'0xf'
,则返回该十六进制转换为十进制的值 - 如果字符串包含上述情况之外其他字符,则返回
NaN
- 如果是空字符串,返回
- 对象,调用
valueOf()
方法,并按照上述规则转换返回的值。如果转换结果是NaN
,则调用toString()
方法,再按照转换字符串的规则转换。
Number(undefined) //NaN
Number(null) //0
Number(true) //1
Number(1111) // 1111
Number(23n) //23
Number('') //0
Number('1111') //1111
Number('11.11') //11.11
Number('0xf') // 16
Number('hello world') // NaN
Number({}) //NaN
//注:一元操作符'+'与Number()遵循相同的规则
+true //1
+undefined //NaN
parseInt()
parseInt
函数接收两个参数,第一个参数为要解析的值,第二个参数为要解析的值得底数(可选)。通常在解析字符串为数值时,可优先使用parseInt
函数。
由于早期的
parseInt
函数是绑定在window
对象上的,所以可以直接调用,但其实,现在parseInt
函数已经成了Number
的一个方法
Number.parseInt === window.parseInt //true
parseInt()
会忽略前面的空格,从非空格字符开始解析。直到解析到结尾或者遇到非数值字符。
Number.parseInt('123') //123 不传第二个参数,默认解析规则为十进制
Number.parseInt('123', 16) // 291
Number.parseInt(' 123') //123
Number.parseInt('123value') //123
Number.parseInt('') //NaN
Number.parseInt('AF', 16) //175 显示解析为十六进制,可不用加0x前缀
Number.parseInt('AF') //NaN
parseFloat()
parseFloat()
与parseInt()
类似,只是只接受一个参数,即要解析的值。
Number.parseFloat('11.11') //11.11
Number.parseFloat('11.11value') //11.11
Number.parseFloat(' 11.11') //11.11
Number.parseFloat('11.11.11') //11.11 //只能解析第一个小数点
Number.parseFloat('0xA') //0 //只解析十进制