数据类型

Updated at 2018.07.19, 876 words, 4 mins
Table of Contents

JavaScript 中的数据类型有:StringNumberBooleanNullUndefinedObjectSymbol 七大类。其中常见的有前六个。

数据分类

StringNumberBooleanNullUndefined 被称为基础类型数据,而 Object 类型的数据被称为引用类型数据。

数据存储

基础类型的数据直接存储于栈内存(stack)中。而 引用类型 的数据存储于堆内存(heap)中,栈内存中存储的是数据在堆内存中的引用地址,而不是真正的数据。

网络上很多人的博客都配有示意图,很容易搜索到,这里就不放示意图了。

数据拷贝

基本类型

基础类型的数据,进行数据的拷贝是真正的数据拷贝,拷贝完的两份数据没有任何关联(在这个层面上叫做两个变量不相等)。例如:

var a = 1;
var b = a;

console.log(a); // 1
console.log(b); // 1
console.l(a === b); // true

b = 2;

console.log(a); // 1
console.log(b); // 2
console.log(a === b); // false

可以看出,a 和 b 完全没有关系,更改 b 的值不影响 a 的值。

引用类型

引用类型的数据在进行比较的时候,比较的是堆内存地址:

var a = { name: 'a' };
var b = a;

console.log(a); // { name: 'a' }
console.log(b); // { name: 'a' }
console.l(a === b); // true

b.name = 'b';

console.log(a); // { name: 'b' }
console.log(b); // { name: 'b' }
console.log(a === b); // true

这个例子看出来,b 与 a 是有关联的,将 a 的值(引用地址)拷贝给 b 之后,b 中存储的是和 a 完全一样的引用地址,那么更改 b 中的值(b.name = 'b'),也就是更改了真正的数据,那么打印出 a 的时候,发现 a 中的数据也受到了影响,因为 a 和 b 都指向的是同一个引用地址。因此表现为更改 b 的值,a 的值也受到了影响,拷贝完的两份数据是有关联的(在这个层面上也叫做两个变量不完全不等)。

以此类推,如果引用类型的数据在堆内存中又引用了其他的引用类型的数据呢(比如对象的属性值也是一个对象)?那么比较两个数据是否完全相等或完全不等就相对麻烦。如果不搞清楚这两个概念,可能会导致一些意外的错误,也正因为这个缘故,引出了对象的深拷贝问题(如何使两个对象一模一样但完全不等),这也是前端工程师的经典面试题之一。

目前没有真正的对象深拷贝方法,常用的方法有 JSON.parse(JSON.stringify(obj)) 以及自行编写的 deepCopy 函数,递归进行拷贝。虽然这些都不是真正的对象深拷贝,但是在实践中,这两个方法能解决大部分问题。

完。