JS数据类型
# JS 数据类型有哪些?
JS 的数据类型分为两大类,一是原始类型,二是对象类型。原始类型存储的是值,一般存储在栈上,对象类型存储的是指针,一般存储在堆上。
# 原始类型
Boolean 类型
Boolean 类型表示一个逻辑实体并且包括两个值:
true
和false
。Null 类型
Null 类型只有一个值:
null
。表示没有任何对象。但是
typeof null
会输出object
,所以不能通过typeof
来判断null
。Undefined 类型
Undefined 类型只有一个值:
undefined
。表示没有任何值。没有值(
return;
)的return
语句,隐式返回undefined
。访问不存在的对象属性(
obj.iDontExist
),返回undefined
。变量声明时没有初始化(
let x;
),隐式初始化为undefined
。许多如
Array.prototype.find()
和Map.prototype.get()
的方法,当没有发现元素时,返回undefined
。Number 类型
Number 类型是一种双精度 64 位二进制格式的值。
NaN
(“Not a Number”)是一个特殊种类的数值,当算术运算的结果不表示数值时,通常会遇到它。BigInt 类型
BigInt 类型在 Javascript 中是一个数字的原始值,它可以表示任意大小的整数。
String 类型
String 类型表示文本数据并编码为 UTF-16 代码单位的 16 位无符号整数值序列。
Symbol 类型
Symbol 是唯一并且不可变的原始值并且可以用来作为对象属性的键。
原始类型存储的都是值,是没有函数可以调用的。
# 对象类型
当创建了一个对象类型的时候,计算机会在堆内存中帮我们开辟一个空间来存放值,但是我们需要找到这个空间,这个空间会拥有一个地址(指针)。
# 数据类型检测的方式有哪些?
# typeof
console.log(typeof 2) // number
console.log(typeof true) // boolean
console.log(typeof 'str') // string
console.log(typeof []) // object
console.log(typeof function () {}) // function
console.log(typeof {}) // object
console.log(typeof undefined) // undefined
console.log(typeof null) // object
2
3
4
5
6
7
8
其中数组、对象、null 都会被判断为 object,其他判断都正确。
# instanceof
instanceof
可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。
console.log(2 instanceof Number) // false
console.log(true instanceof Boolean) // false
console.log('str' instanceof String) // false
console.log([] instanceof Array) // true
console.log(function () {} instanceof Function) // true
console.log({} instanceof Object) // true
2
3
4
5
6
7
instanceof
只能正确判断引用数据类型,而不能判断基本数据类型。instanceof
运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype
属性。
# constructor
console.log((2).constructor === Number) // true
console.log(true.constructor === Boolean) // true
console.log('str'.constructor === String) // true
console.log([].constructor === Array) // true
console.log(function () {}.constructor === Function) // true
console.log({}.constructor === Object) // true
2
3
4
5
6
constructor
有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor
对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor
就不能用来判断数据类型了:
function Fn() {}
Fn.prototype = new Array()
var f = new Fn()
console.log(f.constructor === Fn) // false
console.log(f.constructor === Array) // true
2
3
4
5
6
7
8
# Object.prototype.toString.call()
Object.prototype.toString.call()
使用 Object
对象的原型方法 toString
来判断数据类型:
var a = Object.prototype.toString
console.log(a.call(2)) //[object Number]
console.log(a.call(true)) //[object Boolean]
console.log(a.call('str')) //[object String]
console.log(a.call([])) //[object Array]
console.log(a.call(function () {})) //[object Function]
console.log(a.call({})) //[object Object]
console.log(a.call(undefined)) //[object Undefined]
console.log(a.call(null)) //[object Null]
2
3
4
5
6
7
8
9
10
同样是检测对象 obj 调用toString
方法,obj.toString()
的结果和Object.prototype.toString.call(obj)
的结果不一样,这是为什么?
这是因为toString
是Object
的原型方法,而Array
、function
等类型作为Object
的实例,都重写了toString
方法。
不同的对象类型调用toString
方法时,根据原型链的知识,调用的是对应的重写之后的toString
方法(function
类型返回内容为函数体的字符串,Array 类型返回元素组成的字符串…),而不会去调用Object
上原型toString
方法(返回对象的具体类型),所以采用obj.toString()
不能得到其对象类型,只能将 obj 转换为字符串类型。
因此,在想要得到对象的具体类型时,应该调用Object
原型上的toString
方法。
# instanceof 能否判断基本数据类型?
对于原始类型来说,想直接通过 instanceof
来判断类型是不行的,但是我们还是有办法实现的,比如下面这种方式:
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === 'number'
}
}
console.log(111 instanceof PrimitiveNumber) // true
2
3
4
5
6
Symbol.hasInstance
用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个类上的行为。
其实就是自定义 instanceof
行为的一种方式,这里将原有的 instanceof
方法重定义,换成了 typeof
,因此能够判断基本数据类型。