相信人不少學習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; };