首先增加了Object的clone方法,代码如下:
/**
* 对象复制
* @param expKey 不复制的键正则表达式或名
* @return 复制的对象
*/
Object.prototype.clone = function(expKey){
let map = new WeakMap();
let src = this;
let retObj = clone(src);
map = null;
return retObj;
/**
* clone对象
* @param src 待clone对象
* @return 克隆后的对象
*/
function clone(src){
function clone(src){
var dst;
if(nodom.isObject(src)){
dst = new Object();
//把对象加入map,如果后面有新克隆对象,则用新克隆对象进行覆盖
map.set(src,dst);
Object.getOwnPropertyNames(src).forEach((prop)=>{
//不克隆的键
if(expKey){
if(expKey.constructor === RegExp && expKey.test(prop) //正则表达式匹配的键不复制
|| expKey.constructor === String && expKey === prop //被排除的键不复制
){
return;
}
}
//数组或对象继续克隆
if(nodom.isObject(src[prop]) || nodom.isArray(src[prop])){
let co = null;
if(!map.has(src[prop])){ //clone新对象
co = clone(src[prop]);
//存储已克隆对象,避免重复创建或对象相互引用带来的溢出
map.set(src[prop],co);
}else{ //从map中获取对象
co = map.get(src[prop]);
}
dst[prop] = co;
}else{ //直接复制
dst[prop] = src[prop];
}
});
} else if(nodom.isArray(src)){
dst = new Array();
//把对象加入map,如果后面有新克隆对象,则用新克隆对象进行覆盖
map.set(src,dst);
src.forEach(function(item,i){
if(nodom.isObject(item) || nodom.isArray(item)){
dst[i] = clone(item);
}else{ //直接复制
dst[i] = item;
}
});
}
return dst;
}
}
}());
改写merge方法,调用了Object.assign方法和Object的clone(见上面扩展)方法:
/**
* 合并多个对象并返回
* @param 参数数组
* @return 返回对象
*/
static merge(){
for(let i=0;i<arguments.length;i++){
if(!nodom.isObject(arguments[i])){
throw nodom.Error.handle('invoke','nodom.merge',i,'object');
}
}
let retObj = Object.assign.apply(null,arguments);
subObj(retObj);
return retObj;
//处理子对象
function subObj(retObj){
for(let o in retObj){
if(nodom.isObject(retObj[o]) || nodom.isArray(retObj[o])){ //对象或数组
retObj[o] = retObj[o].clone();
}
}
}
}