JS数据类型
基础数据类型与引用数据类型
基本概念
众所周知,js有两类数据类型,基础数据类型和引用数据类型。
- 基础数据类型主要有:
Undefined、Null、Boolean、Number、String; - 引用数据类型:
Object;
这时候可能有些人就会有疑问了,我们通常使用的Array属于那种类型呢?
来看一下ECMA官方文档(可以从官网上下载的ECMA-262.pdf)上的说明:The Array constructor is the %Array% intrinsic object and the initial value of the Array property of the global object. When called as a constructor it creates and initializes a new exotic Array object.
这一段简单翻译一下就是:Array 构造函数是 %Array% 内在对象和全局对象的 Array 属性的初始值。当作为构造函数调用时,它会创建并初始化一个新的奇异数组对象。
通过这段话我们可以得知,Array其实本质上是一个Object对象,这也符合大家经常说的“万物皆对象”说法。
同样的,还有Date,function也是Object。
两者区别
说到二者的区别,首先可以从字面上做对比,一个是“基础”,一个是“引用”,那么这个“基础”和“引用”又作何理解呢?
1、二者的存储机制:
- 基础数据类型是存储在栈--stack中的简单数据字段,其值直接存储在访问变量访问的位置;
- 引用数据类型是存储在堆--heap中的对象,也就是存储在变量处的值是一个指针--point,指向存储对象的内存地址;
2、当我们对两种数据类型进行值的复制的时候,二者也是有区别的:
- 基础数据类型:将值的副本赋值给新的变量;
- 引用数据类型:将值的引用地址赋值给新的变量;
下面通过代码结合图示展示二者在存储上的区别:
基础数据类型:
var numOne = 5
var numTwo = numOne
引用数据类型:
var objOne = new Object()
var objTwo = objOne
由此,可以引出一个问题:为什么js中的引用数据类型要采用堆进行存储呢?
答:因为引用值的大小是会变化的,如果放在栈中会影响变量的查询速度,js采用的是在变量的栈空间放入该对象存储在堆中的地址。由于地址的大小是固定的,所以把它存储在在栈中对变量的查询速度没有影响。
ES6 Symbol
基础概念
Symbol是ES6新引入的一种基础数据类型,表示独一无二的值;
用法
Symbol的语法:Symbol([description]),其中description是个可选参数,
let s = Symbol('foo')
typeof s // "Symbol"
console.log(s) // "Symbol(foo)"
通过以上代码,就可以创建让s成为一个独一无二的值,那么,怎么理解这个独一无二呢?
let s1 = Symbol('foo')
let s2 = Symbol('foo')
console.log(s1, s2, s1 === s2); // "Symbol(foo)" "Symbol(foo)" false
可以看到,虽然s1和s2都是通过Symbol构造的,且参数相同,且通过打印虽然二者值相等,但是实际做全等比较是不相等的。
那么,如果Symbol的参数是个对象,这时候会是什么情况呢?
let obj1 = {
toString() {
return 'obj1.toString'
}
}
let obj2 = {
testKey: 'obj12.testValue'
}
let s1 = Symbol(obj1)
let s2 = Symbol(obj2)
console.log(s1, s2); // Symbol(obj1.toString) Symbol([object Object])
可以发现,当参数是对象时,Symbol会先调用对象的toString方法,将其转换为字符串,然后再生产一个Symbol值。
用途
通过上文,我们可以认识到了何谓“独一无二的值”,那么,Symbol的这种特性可以用来干什么呢?
- 作为属性名:由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。
- 定义常量:由于独一无二的特性,我们可以通过Symbol定义一组常量,并将其和
switch case结合使用。
BigInt
除了上文中介绍的几种数据类型,还有一个基础数据类型--BigInt。
它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript中可以用 Number表示的最大数字。BigInt可以表示任意大的整数。
这个地方不太常用就不展开讲了,涉及具体定义及API可以参考MDN文档,文章末尾有粘贴。