浅拷贝与深拷贝多种实现
程序员文章站
2022-04-27 08:45:45
...
目录
浅拷贝
拷贝对象
使用for in循环实现
测试对象: obj(源), obj2(目标)
let obj = {
a:"1",
b:"man",
func:function(){
console.log("测试");
},
ob:{
ab:"第二层",
sex:"women"
},
c:[],
arr:[1,23,4,"str",{name:"数组里面的测试对象"}
}
let obj2 = {};
简单实现
for(let prop in obj){
obj2[prop] = obj[prop];
}
使用assign实现
Object.assign(obj2,obj);
使用扩展运算符实现
obj2 = {obj};
使用JSON对象拷贝
let tmp = JSON.stringify(obj);
obj2 = JSON.parse(tmp);
拷贝数组
使用slice或concat拷贝
测试用例 arr1(源), arr2(目标)
let arr1 = ["a",1,{name:"第二层",arrDeep:[1,23,5,7]}];
let arr2 = [];
arr2 = arr1.slice();
arr2 = arr1.concat();
//结果返回的是新的引用 ,但是内容第二层会变为arr1的引用
["a", 1, {name:"第二层",arrDeep:[1,23,5,7]}]
使用for遍历实现也行 跟对象的内容差不多
深拷贝
使用constructor判断
测试对象: obj(源), obj2(目标)
let obj = {
a:"1",
b:"man",
func:function(){
console.log("测试");
},
ob:{
ab:"第二层",
sex:"women"
},
c:[],
arr:[1,23,4,"str",{name:"数组里面的测试对象"}
}
let obj2 = {};
代码测试及结果
function deepClone(origin){
let target = origin.constructor === Array? []:{};//判断复制源为什么类型
for(let prop in origin){
if(origin.hasOwnProperty(prop)){//是否为原型链上的属性
if(typeof origin[prop] == "object"){//判断是否为基本数据类型
origin[prop].constructor === Array ? target[prop] = []:target[prop] = {};
target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身
}else{
target[prop] = origin[prop];//正常复制
}
}
}
return target;
}
obj2 = deepClone(obj);
使用Object.prototypy.toString.call()判断
代码测试及结果
function deepClone(origin){
let toStr = Object.prototype.toString;//保存函数引用
let arrayStr = "[object Array]"; //储存调用函数判断为数组时返回的值
let target = toStr.call(origin) == arrayStr? []:{};//判断复制源为什么类型
for(let prop in origin){
if(origin.hasOwnProperty(prop)){//是否为原型链上的属性
if(typeof origin[prop] == "object"){//判断是否为基本数据类型
toStr.call(origin[prop]) == arrayStr ? target[prop] = []:target[prop] = {};
target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身
}else{
target[prop] = origin[prop];//正常复制
}
}
}
return target;
}
obj2 = deepClone(obj);
使用Array.isArray()判断
代码测试及结果
function deepClone(origin){
let toStr = Object.prototype.toString;//保存函数引用
let arrayStr = "[object Array]"; //储存调用函数判断为数组时返回的值
let target = toStr.call(origin) == arrayStr? []:{};//判断复制源为什么类型
for(let prop in origin){
if(origin.hasOwnProperty(prop)){//是否为原型链上的属性
if(typeof origin[prop] == "object"){//判断是否为基本数据类型
toStr.call(origin[prop]) == arrayStr ? target[prop] = []:target[prop] = {};
target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身
}else{
target[prop] = origin[prop];//正常复制
}
}
}
return target;
}
obj2 = deepClone(obj);
结果
总结
深度拷贝分为一下几步:
- 判断复制目标为数组还是对象
- 循环遍历属性(注意排除原型链上的属性)
- 先用typeof判断是否为基本属性
- 若是则直接复制
- 若不是 则使用函数判断为数组或者为对象,分别赋值并递归调用自身
上一篇: 编写php拓展实例
下一篇: 深拷贝&浅拷贝 & 它们的实现