js中的深复制
需求:
1.既可以广度复制,也能深度复制
2.复制的类型包括Date,HTML,正则,数组,对象,基础类型,可枚举的,不可枚举的等
3.深层的属性值改变,复制过去的不发生改变
下面来看代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//复制对象的举例
var obj={
a:1,
b:2,
c:[1,2,3],
z:document.createElement("div"),
d:{
e:new Date(),
f:/a/g,
g:function(s){
console.log(s);
},
h:{
}
}
}
Object.defineProperties(obj.d.h,{
i:{
value:10
},
j:{
configurable:true,
value:[1,2,3,4]
},
k:{
writable:true,
value:{
l:{},
m:"abcde",
n:true,
o:[1,2,3]
}
}
})
Object.defineProperties(obj.d.h.k.l,{
p:{
value:function(){
console.log("p")
}
},
q:{
value:{
r:{a:1},
j:{b:2}
}
}
});
console.log(obj);
function cloneObj(source,target){
// if(target==undefined) target={};
target=target||{};
var names=Object.getOwnPropertyNames(source); //为了遍历不可枚举属性 获取对象的所有属性
for(var i=0;i<names.length;i++){
var desc=Object.getOwnPropertyDescriptor(source,names[i]); //获取对象属性的描述属性
if(typeof desc.value==="object" && desc.value!==null){ //不是object的只有五种基本类型
var obj;
switch(true){
case desc.value.constructor===Date:
obj=new Date(desc.value.toString());
break;
case desc.value.constructor===RegExp:
obj=new RegExp(desc.value.source,desc.value.flags);
break;
case HTMLElement.isPrototypeOf(desc.value.constructor):
obj=document.createElement(desc.value.nodeName);
break;
default:
obj=new desc.value.constructor() //根据属性值的类型来创建obj(如果是数组,复制数组,如果对象,就复制对象)
}
Object.defineProperty(target,names[i],{
enumerable:desc.enumerable,
writable:desc.writable,
configurable:desc.configurable,
value:obj
});
cloneObj(desc.value,obj);
}else{
Object.defineProperty(target,names[i],desc)
}
}
return target;
}
var o={a:1};
o=cloneObj(obj);
obj.d.h.j[1]=100;
console.log(o);
</script>
</body>
</html>