JS数据类型:基础、引用以及ES6 Symbol

253 阅读4分钟

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

基本类型复制变量值.png

引用数据类型:

var objOne = new Object()
var objTwo = objOne

引用类型复制变量值.png

由此,可以引出一个问题:为什么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文档,文章末尾有粘贴。

参考文档

阮一峰-Symbol

MDN-BigInt