· 714 words · 4 min
JavaScript 中的数据类型有:String
、Number
、Boolean
、Null
、Undefined
、Object
、Symbol
七大类。其中常见的有前六个。
String
、Number
、Boolean
、Null
、Undefined
被称为基础类型
数据,而 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
函数,递归进行拷贝。虽然这些都不是真正的对象深拷贝,但是在实践中,这两个方法能解决大部分问题。
完。