前言
浅拷贝和深拷贝往往指的是引用数据类型的值引用的问题,要分清什么是浅拷贝和深拷贝,就得先聊聊 JavaScript 的数据存储方式
数据类型
JavaScript 把数据类型分为两类:基本数据类型和引用数据类型
基本数据类型:存放在栈内存上。其中,JS 有 5 个,ES 有 2 个
number、string、boolean、null、undefined
ES 引入的数据类型:BigInt、Symbol
引用数据类型:是指由类型的实际值引用(类似于指针)表示的数据类型。引用数据类型是存放在堆内存中的对象,变量其实是保存的在栈内存中的一个指针(保存的是堆内存中的引用地址),这个指针指向堆内存对应的对象
Object、Array
-
浅拷贝:仅仅分配一个指针指向原对象内存地址
-
深拷贝:分配一个新指针和新地址
浅拷贝
浅拷贝指的是只拷贝堆地址的引用
var arr = [1,2,3];
var arrs = arr; // 复制
arrs.push(4); // 修改复制
console.log(arr); // [1, 2, 3, 4] arr也发生改变
深拷贝
深拷贝堆是指内存中开辟一块新的空间,把原对象的值复制到新的空间,引用指向新的地址
Object.assign
Object.assign(target, obj)
当对象的层级只有一级时,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性后就是浅拷贝
JSON 转换
JSON.prase(JSON.stringify(obj))
一般使用 try catch
包裹。同时可以通过发送日志的,再使用日志中台统计我们的各种报错原来,来发现我们开发过程中的前端或者后端的不规范,不合理等
问题:会导致对象中包含
function
、undefined
、正则、时间对象等丢失
递归
function deepClone(){
const targetObj = obj.constructor === Array ? [] : {}; // 判断复制的目标结果是数组还是对象
for(let keys in obj){ // 遍历目标
if(obj.hasOwnProperty(keys)){
if(obj[keys] && typeof obj[keys] === 'object'){ // 如果值是对象,就递归一下
res[keys] = obj[keys].constructor === Array ? [] : {};
res[keys] = deepClone(obj[keys]);
} else { // 如果不是,就直接赋值
res[keys] = obj[keys];
}
}
}
return res;
}
问题:对象内存在循环引用会导致递归死循环