要了解 深浅拷贝我们需要先了解一下js的内存机制
我们先写个例子更直观的去看一下
let a = 10
let b = a
a = 20
console.log(a, b);
// 打印结果 20,10
let obj1 = { name: "小明" }
let obj2 = obj1
obj1.name = "小红"
console.log(obj1.name, obj2.name);
// 打印结果 小红,小红
上图我们可以看出b=a ,a的值发生改变,但是b的值没有发生改变,而对象的赋值则会改变, 下面我们先看一下 js 的栈内存和堆内存
栈内存 主要用于存储各种基本类型的变量,包括Boolean、Number、String、Undefined、 Null,**以及对象变量的指针
堆内存 主要负责像对象Object这种变量类型的存储
深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个
浅拷贝:赋值时,引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个
基本类型是储存在栈内存空间的引用类型的堆内存空间
从上图可以看出 基本数据类型赋值为深拷贝 引用数据类型赋值为浅拷贝,这里也就解释了为啥
JSON.stringify(),JSON.parse()可以进行深拷贝,但是这个有bug,大家可以下去百度一下
接下来我们一步一步的写一个深拷贝的方法
我们先定义一个方法 通过for in来便利对象 ,并通过hasOwnProperty来检测一下对象是否包含特 定的自身属性
let obj1 = { name: "小明" }
function deepClone(source) {
let targetObj = Array.isArray( source ) ? [] : {} //这里我们需要兼容一下数组
for (const key in source) {
if (source.hasOwnProperty(key)) {
//判断对象是否包含特定的自身(非继承)属性,防止有些对象属性被delete删除掉
targetObj[key] = source[key]
//给新对象通过key值赋值拷贝
console.log(key);
}
}
return targetObj
}
let obj2 = deepClone(obj1)
obj1.name = "小红"
console.log(obj1.name, obj2.name);
//打印结果 小红 , 小明
上面这个方法只能拷贝外层,所以我们需要用到递归去深层次的拷贝 ,
let obj1 = { name: "小明", people: { age: 13 } }
function deepClone(source) {
if (typeof source !== 'object') return source//这里不是对象直接返回
let targetObj = Array.isArray( source ) ? [] : {} //数组兼容
for (const key in source) {
if (source.hasOwnProperty(key)) {
//判断对象是否包含特定的自身(非继承)属性,防止有些对象属性被delete删除掉
if (source[key] && typeof source[key] === 'object') {
targetObj[key]=deepClone(source[key]) //通过递归进行深层次拷贝
} else {
targetObj[key] = source[key]
}
}
}
return targetObj
}
let obj2 = deepClone(obj1)
obj1.name = "小红"
console.log(obj1, obj2);
上面这个应该看懂问题不大吧!我就不做过多解释了