相信人不少学习js的过程当中都踩了深拷贝和浅拷贝的坑,深拷贝和浅拷贝的区别我就再也不赘述了,今天我来写一下我本身实现深拷贝的各类方法。
比较简单的拷贝方式能够借用浏览器的Json对象去实现,先把对象转化为json字符串,在解析回对象实现深拷贝。具体代码就是JSON.parse(JSON.stringify(target));可是这种比较hack的方法总归不是正途,如今我就来贴两种我本身写的深拷贝代码。json
function deepClone(currobj){ if(typeof currobj !== 'object'){ return currobj; } if(currobj instanceof Array){ var newobj = []; }else{ var newobj = {} } for(var key in currobj){ if(typeof currobj[key] !== 'object'){ newobj[key] = currobj[key]; }else{ newobj[key] = deepClone(currobj[key]) } } return newobj }
第一种天然就是递归,遍历对象的每个属性而后赋值到新对象了,如果有深层次嵌套的对象,递归执行函数。jq中的深拷贝也是用相似方法实现。数组
function deepClone(currobj){ if(typeof currobj !== 'object'){ return currobj; } if(currobj instanceof Array){ var newobj = []; }else{ var newobj = {} } var currQue = [currobj], newQue = [newobj]; while(currQue.length){ var obj1 = currQue.shift(),obj2 = newQue.shift(); for(var key in obj1){ if(typeof obj1[key] !== 'object'){ obj2[key] = obj1[key]; }else{ if(obj1[key] instanceof Array ){ obj2[key] = []; }else{ obj2[key] = {} }; currQue.push(obj1[key]); newQue.push(obj2[key]); } } } return newobj; };
上一种递归的方式容易引发内存溢出,特别是对一个比较复杂,层级很深的对象进行深拷贝。因此第二种方法是用循环去拷贝次级的对象,用两个队列去保存须要拷贝的对象和拷贝目标,利用浅拷贝的原理实现了深拷贝。浏览器
可是有时候对象会存在子属性指向自身的问题,造成对象环,我这暂时尚未考虑到。
忽然看到本身这篇文章,其实对象环的问题只须要别将旧数组出栈就好了具体代码:函数
function deepClone(currobj){ if(typeof currobj !== 'object'){ return currobj; } if(currobj instanceof Array){ var newobj = []; }else{ var newobj = {} } var currQue = [currobj], newQue = [newobj], i = 0; while(i <= currQue.length - 1){ var obj1 = currQue[i++],obj2 = newQue.shift(); for(var key in obj1){ if(typeof obj1[key] !== 'object'){ obj2[key] = obj1[key]; }else{ if(currQue.includes(obj1[key])){ obj2[key] = obj1[key]; continue; } if(obj1[key] instanceof Array ){ obj2[key] = []; }else{ obj2[key] = {} }; currQue.push(obj1[key]); newQue.push(obj2[key]); } } } return newobj; };