一:Why deepClone?
说到深拷贝(拷贝基本适用于引用类型的拷贝),就不得不说JS数据类型、浅拷贝、栈/堆。
- JS数据类型
1:基本类型
String、Number、Boolean、Null、Undefined.
2:引用类型
Object、Arry、 Function
- 栈/堆
1:栈(Stack)
内存中开辟地址,直接赋值,占据固定大小的空间。
2:堆(Heap)
存放对象数值,在栈内存中保存一个指针的地址,此地址指向堆中保存的数值
- 浅拷贝
浅拷贝是直接引用在栈中的指针的地址,此地址指向真正保存在堆中的数值。故任何一方只要改变对象的数值。双方数值都会改变
- 深拷贝
重新在堆中生成新的数值,栈中生成新的指针地址。即使改变拷贝之后对象的属性值,原始对象值不会改变,没有影响。
let obj1={
age:17,
sex:"woman",
address:{
city:'shenzhen'
},
arr:[1997,"百度",2000,"alibaba"]
}
let obj2=obj1;
console.log("obj2:",obj2)
obj2.age=34;
console.log("改变obj2的age值之后","obj1:",obj1);
console.log("改变obj2的age值之后","obj2:",obj2);
二:How deepClone?
- ES5结构赋值(局限性:只适用一维数据)
let obj1={
a:11,b:22
}
let obj2={...obj1}
obj2.a='obj2'
console.log('使用ES5解构改变obj2之后-obj1:',obj1)
console.log('使用ES5解构改变obj2之后-obj2:',obj2)
let ary1=[1,2]
let ary2=[...ary1]
ary2.push('ary2')
console.log('使用ES5解构改变ary2之后-ary1:',ary1)
console.log('使用ES5解构改变ary2之后-ary2:',ary2)
- JSON对象(局限性:对于function不生效,请自行验证)
let obj1={
a:11,b:22
}
let obj2=JSON.parse(JSON.stringify(obj1))
obj2.a='obj2'
console.log('使用JSON对象改变obj2之后-obj1:',obj1)
console.log('使用JSON对象改变obj2之后-obj2:',obj2)
let ary1=[1,2]
let ary2=JSON.parse(JSON.stringify(ary1))
ary2.push('ary2')
console.log('使用JSON对象改变ary2之后-ary1:',ary1)
console.log('使用JSON对象改变ary2之后-ary2:',ary2)
3. 递归(最优解)
function deepClone(obj) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
let reslut = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
reslut[key] = deepClone(obj[key])
}
}
return reslut
}
let obj1 = {
age: 17,
address: {
"province": "广东",
"city": "深圳"
}
}
let obj2 = deepClone(obj1);
obj2.address.province = "陕西";
obj2.address.city = "西安";
console.log('使用深拷贝改变obj2之后-obj1:',obj1)
console.log('使用深拷贝改变obj2之后-obj2:',obj2)