7 种类型
- String
- Number
- Boolean
- Null
- undefined
- Symbol
- Object
类型判断
使用 typeof
类型判断
typeof undefined // "undefined"
typeof true // "boolean"
typeof 1 // "number"
typeof 's' // "string"
typeof {} // "object"
typeof Symbol() // "symbol"
// 特殊类型
typeof null // "object"
// 检测 null 值的类型
const a = null
!a && typeof a === 'object' // true
object
类型中还包含很多的’子类型’, Array、Function、Date、RegExp、Error, 但是函数例外
typeof function a() {} === 'function' // true
function(函数)也是 JavaScript 的一个内置类型。实际上是 object 的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性
[[Call]]
,该属性使其可以被调用
//typeof 只有 function 的情况下返回 'function',其他类型都返回 `object`
typeof new Date() // object
typeof new Error() // object
Object.prototype.toString
更详细的检测类型
- 如果
this
值是undefined
,就返回[object Undefined]
- 如果
this
的值是null
,就返回[object Null]
- 返回由
"[object ", class and "]"
三个部分组成的字符串至少 17 种类型:Number, String, Boolean, Undefined, Null, Object, Function, Array, Date, Error, RegExp, Math, JSON, Arguments Symbol Set Map
// demo 返回的 `class` 就是我们期望的类型, 与 `typeof` 不同的是,这里返回的类型,首字母都是大写的
Object.prototype.toString.call(undefined) // [object Object]
Object.prototype.toString.call(null) // [object Object]
Object.prototype.toString.call(Symbol()) //[object Symbol]
Object.prototype.toString.call(new Set()) //[object Set]
Object.prototype.toString.call(new Map()) //[object Map]
Object.prototype.toString.call(new Date()) // [object Date]
Object.prototype.toString.call(Math) // [object Math]
a = () => {
console.log(Object.prototype.toString.call(arguments)) // [object Arguments]
}
a()
function classType() {
const classType = {}
// 来自 `冴羽的 JavaScript 专题系列`
// 生成classType映射
'Boolean Number String Function Array Date RegExp Object Error Symbol Set Map'
.split(' ')
.map((item, index) => {
classType['[object ' + item + ']'] = item.toLowerCase()
})
type = obj => {
// 一箭双雕
if (obj == null) {
return obj + ''
}
return typeof obj === 'object' || typeof obj === 'function'
? classType[Object.prototype.toString.call(obj)] || 'object'
: typeof obj
}
}
类型值简介
Undefined
和 null
undefined
类型只有一个值,即 undefined
。null
类型也只有一个值,即 null
。它们的名称既是类型也是值。
undefined
指从未赋值,undefined
却是一个标识符,在非严格条件下可以被当作变量来使用和赋值, 在严格模式下可以声明一个名为undefined
的局部变量null
指曾赋过值,但是目前没有值,null
是一个JavaScript
关键字,不是标识符,我们不能将其当作变量来使用和赋值
void
运算符: 表达式void ___
没有返回值,因此返回结果是undefined
。
为了避免无意中被篡改,使用void 0
来获取undefined
值
String
String
有最大长度是 2^53 - 1
,String
的意义并非“字符串”,而是字符串的 UTF16
编码,我们字符串的操作 charAt
、charCodeAt
、length
等方法针对的都是 UTF16
编码, JavaScript
中的字符串是永远无法变更的,一旦字符串构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征
区别于数组:
let a = 'foo'
let b = ['f', 'o', 'o']
a[1] = 'O' // "foo" 字符串是不可变的
// a.charAt(1) 取值是不是更优雅一些
b[1] = 'O' // ["f","O","o"]
// 字符串不能直接反转,数组可以
a.reverse() //undefined
b.reverse() //["o","o","f"]
// 实现字符串反转
a.split('')
.reverse()
.join('') // ["o","o","f"]
Number
JavaScript
中的Number
类型有18437736874454810627
(即2^64-2^53+3
) 个值
JavaScript
为了表达几个额外的语言场景(比如不让除以 0
出错,而引入了无穷大的概念),规定了几个例外情况:
- NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字;
- Infinity,无穷大;
- -Infinity,负无穷大
JavaScript
中有+0
和-0
,在加法类运算中它们没有区别,但是除 法的场合则需要特别留意区分,“忘记检测除以-0
,而得到负无穷大”的情况经常会导致 错误,而区分+0
和-0
的方式,正是检测1/x
是Infinity
还是-Infinity
NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不 成立)的值。而
NaN != NaN
为 true,可以使用内建的全局工具函数Number.isNaN(..)
来判断一个值是否是 NaN。
isNaN(…) 和 Number.isNaN(…)
isNaN()
: 全局工具函数isNaN(..)
来判断一个值是否是NaN
, 检查方式就是检查参数是否不是NaN
,也不是数字
const a = 2 / 'foo' //NaN
const b = 'foo'
window.isNaN(a) // true
window.isNaN(b) // true 不是数字也返回 true
Number.isNaN(..)
较小的数值
Number.isNaN(a) // true
Number.isNaN(b) // false
JavaScript
中的 Number
类型基本符合 IEEE 754-2008
规定的双精度浮点数规则,二进制浮点数最大的问题是0.1 + 0.2 === 0.3; // false
二进制浮点数中的
0.1 和 0.2
并不是十分精确,它们相加的结果并非刚好等于0.3
,而是一个比较接近的数字0.30000000000000004
,所以条件判断结果为false
正确的比较方法是使用 JavaScript
提供的最小精度值:console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
整数的检测
要检测一个值是否是整数,可以使用 ES6 中的 Number.isInteger(..) 方法:
Number.isInteger(42) // true
Number.isInteger(42.0) // true
Number.isInteger(42.3) // false
Symbol
它是一切非字符串的对象 key
的集合,在 ES6
规范 中,整个对象系统被用 Symbol
重塑。
Symbol 可以具有字符串类型的描述,但是即使描述相同,Symbol 也不相等。
var mySymbol = Symbol("my symbol")
Object
对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是 key-value
结构,key
可以是字符串或者 Symbol
类型。
注意点:
Number、String 和 Boolean,三个构造器是两用的,当跟new
搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。
3 与new Number(3)
是完全不同的值,它们一个是Number
类 型, 一个是对象类型。
Object.is(..)
判断两个值是否绝对相等,
Object.is(..)
主要用来处理那些特殊的相等比较
Object.is(0 / 'foo', NaN) // true
Object.is(-3 * 0, -0) // true
Object.is(-3 * 0, 0) // false
简单的 polyfill:
if (!Object.is) {
Object.is = function(v1, v2) {
// 判断是否是-0
if (v1 === 0 && v2 === 0) {
return 1 / v1 === 1 / v2
}
// 判断是否是NaN
if (v1 !== v1) {
return v2 !== v2
}
// 其他情况
return v1 === v2
}
}