要复制的对象
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}
}
}
});
深复制函数
function cloneObj(source,target){
if(target==undefined) 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){ //是对象类型时进入条件
var obj;
switch(true){
case desc.value.constructor===Date:
obj=new Date(desc.value.toString()); //是时间类型时:将原来的时间当做参数传入到new Date中,否则因为时间是时刻在变的,复制过来的时间会不一样。
break;
case desc.value.constructor===RegExp:
obj=new RegExp(desc.value.source,desc.value.flags); //如果是正则类型时:将原正则的source与flags当做参数带入,才能获得和原来一样的正则表达式。
break;
case HTMLElement.isPrototypeOf(desc.value.constructor): //判断是否是HTML标签
obj=document.createElement(desc.value.nodeName); //根据原标签的nodeName创建同一类型的HTML标签
break;
default:
obj=new desc.value.constructor();
// 内容.constructor可以判断是什么类型的,比如对象就是Object,数组是Array,所以可以利用这点来new一个相同类型的。
}
Object.defineProperty(target,names[i],{
enumerable:desc.enumerable,
writable:desc.writable,
configurable:desc.configurable,
value:obj
}); //同时把每个属性的描述对象也给target复制过去
cloneObj(desc.value,obj); //将某个对象类型的属性当做参数递归,clone给上边创建的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);