浅谈对象(数组)的深克隆和浅克隆
浅克隆
- object.assign()
- Array.prototype.concat()
- Array.prototype.slice()
深克隆
- JSON.stringify 和 JSON.parse
- Object.assign()
- 通过JQuery中的extend方法实现深拷贝
- lodash.cloneDeep()实现深拷贝
- 递归
注意:当对象只有一层结构的时候,使用Object.assign()是深拷贝,但是对象里面要是有子对象,就是浅拷贝
浅克隆
浅拷贝值复制某个对象的指针,而不是复制对象本身,新旧对象还是使用共同的内存,深拷贝为对象创建另一个一样的对象,修改新对象不会更改旧对象。
所以当浅拷贝的对象中含有二级对象的时候,二级对象的值其实是一个引用地址,该引用地址指向堆内存,当我们拷贝到时候,也是直接考的这个引用地址,所以修改堆中的数据的时候对原始对象和拷贝后的对象都有影响。
以下面这个obj为例,画个图相信大家就懂了。
1、object.assign()
使用Object.assign()是浅拷贝,当对象只有一层的时候是深拷贝,但是有子结构就是浅拷贝
let obj = {
name:'bella',
addr:{
province:'cd',
city:'df'
},
age:13
}
let clone = Object.assign({},obj);
clone.addr.city = 'aaa';
console.log(obj.addr.city);// aaa
2、Array.prototype.concat()
let arr = [1, 3, {
username: 'kobe'
}];
let arr2=arr.concat();
arr2[2].username = 'wade';
console.log(arr[2].username);// wade
3、Array.prototype.slice()
let arr = [1,3,{
username:'bella'
}];
let arr2 = arr.slice();
arr2[2].username = 'dada';
console.log(arr[2].username);//dada
深克隆
1、JSON.stringify 和 JSON.parse
用JSON.stringify把对象转换成字符串,再用JSON.parse把字符串转换成新的对象
可以转成JSON格式的对象才能使用这种方法,如果对象中包含function或者RegExp、Date这些就不能使用这个方法
function deepClone(obj){
let _obj = JSON.stringify(obj);
let objClone = JSON.parse(_obj);
return objClone
}
2、Object.assign()拷贝
当对象中只有一级属性的时候,就是深拷贝,要是有二级属性,在二级属性以后,就是浅拷贝。
3、通过JQuery中的extend方法实现深拷贝
let $ = require("./jquery");
let obj1 ={
a:1,
b:{
f:{
g:1
}
},
c:[1,2,3]
}
let obj2 = $.extend(true,{},obj1);
4、lodash.cloneDeep()实现深拷贝
let _ = require('lodash');
let obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);
5、递归
原理:遍历对象、数组知道里边都是基本数据类型,然后再去复制,就是深度拷贝
这里传过来的obj,要是 是fn(比如)的实例,并且obj.constructor就是fn,所以这里的newObj就是在创建fn的另一个实例(高逼格)
function deepClone(obj) {
// 不直接创建空对象目的:克隆的结果和之前保持相同的所属类
var newObj = new obj.constructor;
if(obj === null) return null;
if(typeof obj !=='object') return obj;
if(obj instanceof RegExp) return new RegExp();
if(obj instanceof Date) return new Date();
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key])
}
}
return newObj;
}