这样一个基本上满足功能的深复制就完成了。先测试一下
let obj = { a:1, arr:[1,3,5,7,9], c:{ num:100 }, fn:function(){ console.log(1) }, date:new Date(), reg:/\.*/g } let obj1 = deepClone(obj); console.log(obj.c === obj1.c); // false 代表复制成功 console.log(obj.fn === obj1.fn);// true 由于方法单纯修改了引用的地址,所以这里是浅复制 console.log(obj.date === obj1.date);// false 代表复制成功 console.log(obj.reg === obj1.reg);// false 代表复制成功再console一下
console.log(obj) console.log(obj1)这样,就完成了deepClone深复制方法
经过深复制后,图解如下
上述代码还有优化空间,参考了lodash库,在进行 new 对象时,可以使用 constructor构造函数 来进行创建新的实例,这样
可以不用判断递归中,是数组还是对象
如果深复制的某一项是某个原型的实例,深复制完成后,依然是该原型的实例
function deepClone(obj){ let newObj = new obj.constructor; if(obj === null) { return cloneNull(obj) } if(typeof obj=='function'){ return cloneFunction(obj) } if(typeof obj!='object') { return cloneOther(obj) } if(obj instanceof RegExp) { return cloneRegExp(obj) } if(obj instanceof Date){ return cloneDate(obj) } if(obj instanceof Array){ for(let index in obj){ newObj[index] = deepClone(obj[index]); // 对数组子项进行复制 } } if(obj instanceof Object){ for(let key in obj){ newObj[key] = deepClone(obj[key]); // 对对象子项进行复制 } } return newObj; } function cloneNull(obj){ // 复制NULL return obj } function cloneFunction(obj){ // 复制方法, //这个方法待完善,暂时未找到能够完美复制function的方案,如果有方案,望指出 return obj } function cloneOther(obj){ // 复制非对象的数据 return obj } function cloneRegExp(obj){ // 复制正则对象 return new RegExp(obj) } function cloneDate(obj){ // 复制日期对象 return new Date(obj) } 最终版本 deepClone然后可以有一个合并版本的,比较节省代码,将下方区分开的复制方法,合并到deepClone中,可以极大地减少代码体积
function deepClone(obj){ // let newObj = new obj.constructor; if(obj === null) return obj // if(typeof obj=='function') return obj // 由于typeof obj=='function'也符合下方的typeof obj!='object',所以此条可以省略 if(typeof obj!='object') return obj if(obj instanceof RegExp) return new RegExp(obj) if(obj instanceof Date) return new Date(obj) // 运行到这里,基本上只存在数组和对象两种类型了 for(let index in obj){ newObj[index] = deepClone(obj[index]); // 对子项进行递归复制 } return newObj; }