//ES5
function cloneObject(sourceObj,targetObj){
//如果目标对象没传参则进入
if(!targetObj){
//如果对象类型是事件正则类型
if(sourceObj.constructor === RegExp){
//创建一个类型为正则的目标对象
targetObj = new RegExp(sourceObj.source,sourceObj.flags);
//如果是非正则类型
}else{
//创建一个源对象类型
targetObj = new sourceObj.constructor();
}
}
//将源对象的所有属性名以数组的形式获取
var names = Object.getOwnPropertyNames(sourceObj);
//对names做一个循环
for(var i = 0 ; i < names.length ; i++){
//根据每一个属性名获取该对象的描述对象(是否枚举、可写、可删除、可修改,value是值)
var desc = Object.getOwnPropertyDescriptor(sourceObj,names[i]);
//判断描述对象的value是有引用的对象类型,并且非空
if(typeof desc.value === "object" && desc.value !== null){
//这种情况就需要进一步对他的子对象进行复制(克隆寻找子元素在进行复制)
//执行克隆函数,将原对象以第一个参数传入,第二个目标对象不传(不传的话默认会走创建源对象)
//最终会返回复制好的目标对象,例如定义返回的变量名为values
var values = cloneObject(desc.value);
Object.defineProperty(targetObj,names[i],{
enumerable:desc.enumerable,
writable:desc.writable,
configurable:desc.configurable,
value:values
})
//否则(value是非对象类型或者是空,进入)
}else{
//直接给目标对象增加这个属性名,并且将这个对象的描述对象赋值给这个新的属性
Object.defineProperty(targetObj,names[i],desc);
}
}
return targetObj;
}
//ES6
const cloneObj = ((sourceObj, targetObj) => {
!targetObj
? sourceObj.constructor === RegExp
? targetObj = new RegExp(sourceObj.source,sourceObj.flags)
: targetObj = new sourceObj.constructor()
: targetObj
Object.getOwnPropertyNames(sourceObj).map((item, index) => {
let desc = Object.getOwnPropertyDescriptor(sourceObj,Object.getOwnPropertyNames(sourceObj)[index])
desc.value !== null && typeof desc.value === 'object'
? Object.defineProperty(targetObj, Object.getOwnPropertyNames(sourceObj)[index], {
enumerable: desc.enumerable,
writable: desc.writable,
configurable: desc.configurable,
value: cloneObj(desc.value)
})
: Object.defineProperty(targetObj, Object.getOwnPropertyNames(sourceObj)[index], desc)
})
return targetObj
})
原生 - 深复制封装
于 2019-09-07 14:36:03 首次发布