对象的深复制
1、Object.getOwnPropertyNames()
方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。Object.getOwnPropertyNames()
返回一个数组,该数组对元素是 obj
自身拥有的枚举或不可枚举属性名称字符串。 数组中枚举属性的顺序与通过 for...in
循环(或 Object.keys
)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。
2、Object.getOwnPropertyDescriptor()
方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined
。
3、isPrototypeOf()
方法用于测试一个对象是否存在于另一个对象的原型链上。
4、Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
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){
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()
}
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;
}