我们知道,JS 中的数据分为基础数据类型 (Undefined, Null, Boolean, Number, String, symbol) 和引用数据类型(object)。
当赋值给变量进行数据保存时,前者保存的是数据实体,后者保存的是数据实体在堆内存中的地址。
为什么会这样?在 JS 中,也有栈内存和堆内存的概念。
栈,是在程序编译时分配,它是连续的内存空间,容量小,系统分配效率高,有后进先出的特性,适合存储简单有固定尺寸的数据,如基础数据。
堆,是在程序运行时申请的某个大小的内存空间,不连续,树形结构。容量大,系统分配效率略低,适合存储尺寸不确定的数据,如 Object。
基础数据的存储是系统直接在栈内存中开出一块空间存值,而 Object 的存储,是先在堆内存中开辟空间存值,然后在栈内存中存址。
本质区别
深拷贝和浅拷贝的本质区别在于对引用类型数据的拷贝,前者拷值,后者拷址。
本文所述的拷贝主要是对象和数组的拷贝。
代码实现
// data type
const whatType = obj => Object.prototype.toString.call(obj).slice(8, -1)
// shallow copy
function shallowCopy(obj) {
let result;
switch (whatType(obj)) {
case "object":
result = {};
break;
case "Array":
result = [];
break;
default:
return obj
}
for (key in obj) {
obj[key] = obj[key]
}
return result
}
// deep copy
const deepCopy = (function f(obj) {
let result;
switch (whatType(obj)) {
case "Object":
result = {};
break;
case "Array":
result = [];
break;
default:
return obj
}
for (key in obj) {
const type = whatType(obj[key])
if ( type=== "Object" || type === "Array") {
result[key] = f(obj[key])
} else {
result[key] = obj[key]
}
}
return result
})
// 深拷贝的另一种简便方式
const deepCopy2 = obj => JSON.parse(JSON.stringfy(obj))