一、简介
浅拷贝:不在堆内存中重新开辟空间,只复制栈内存中的引用地址,本质上两个对象(数组)依然指向同一块存储空间
深拷贝:在堆内存中重新开辟一个存储空间,完全克隆一个一模一样的对象;
二、深拷贝的三种实现方式
1、递归方式
手写实现深拷贝,使用递归实现原对象每一层的拷贝,当遇到基本数据类型时,直接拷贝,遇到引用数据类型时,递归拷贝它的每个属性。(最安全最常用)
function deepCopy(source,target){
for(var key in source) {
if(source.hasOwnProperty(key)){ // 只拷贝当前对象的属性
// 判断是否为引用数据类型
if(typeof source[key] == 'object'){
// 引用数据类型,赋值为数组[]或者对象{},递归进行深拷贝。
target[key] = Array.isArray(source[key])?[]:{};
deepCopy(source[key],target[key]);
} else {
// 基本数据类型---浅拷贝
target[key] = source[key];
}
}
}
}
2、JSON.parse(JSON.stringify(obj))
缺点:
● 拷贝对象的值中如果有‘funciton’,‘undefined’,‘symbol’,在JSON.stringify()序列化后,键值对丢失
● 拷贝RegExp会变成空对象{}
● 对象中含有‘NaN’,‘Infinity’会变成null
● 拷贝Date会变成字符串
3、$.extend
jQuery中$.extend([deep],target,...object);
推荐在JQ中使用
4、lodash工具包
引入成功后,使用lodash提供的函数_.cloneDeep
三、浅拷贝
1、Object.assign
语法:.assign(target, ...sources)
target 目标对象,接收源对象属性的对象,也是修改后的返回值。 sources 源对象,包含将被合并的属性。(一维对象的深拷贝)
2、es6的扩展运算符
使用扩展运算符可以在构造字面量对象的时候,进行属性的拷贝。
语法:{...sources}
sources 源对象,包含将被合并的属性。
3、Array.prototype.concat()
语法:arr.concat(value0, /* … ,*/ valueN)
注:如果省略了所有 valueN 参数,则 concat 会返回调用此方法的现存数组的一个浅拷贝。
4、Array.prototype.slice()
语法:arr.slice(begin, end)
注:如果省略了 begin, end 参数,则 slice 会返回调用此方法的现存数组的一个浅拷贝。