要用遞歸實現深拷貝,首先說說什么是深拷貝和淺拷貝
// 舉一個簡單的例子---以下的obj,obj2可以看做是這里的obj,obj2 var obj = { name : 'zs', age : 18 } // 淺拷貝 var obj2 = obj; obj.name = 'ls'; console.log(obj2) // { name : 'ls' , age : 18 }
這是淺拷貝,單單就是把obj的地址給了obj2,obj改了,obj2也要改。再來說說這obj改了,這里面有點不同。要么 obj改了屬性(數組就是改了元素),要么干脆obj指向另一個地址,例如:obj = 1;針對第一種就是深淺拷貝可以作為判斷依據的,根據改了之后obj2改不改就可以看出深拷貝(不改)還是淺拷貝(改了)。第二種不管深淺拷貝的因為obj的地址變了,obj再怎么改都不會影響obj2,因此obj2肯定不會變,深淺拷貝看不出來的
var obj = { name : 'zs', age : 18 } var obj2 = obj; // obj 自己地址都變了,再怎么折騰影響不了obj2了 obj = 1; console.log(obj2) // { name : 'zs' , age : 18 }
// 以上 obj可以看做第一個對象(數組) ,obj2 可以看做第二個對象(數組) ,為什么不說函數呢? 因為函數本身辦法改內容,聲明的時候已經確定好函數體了,你還能有神通在不改變聲明函數的函數體前提下,后續添加函數體語句?如果可以,請教教我,說真的!
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下重點說說深拷貝 : 說白了深拷貝的目的就是不想讓obj來影響obj2,有點過河拆橋的意思,把好處或愛情給了另一個人,另一個人卻不想讓你打擾她(說多了是淚)
針對以下三種常見情況提供三種方式進行深拷貝 :
① 很純的對象 : 屬性值沒有數組、對象的 var obj2 = Object.assgin({ }, obj)
② 沒有方法的對象 (沒有方法在內,可以有數組和對象充當屬性值) : var obj2 = JSON.parse(JSON.stringify(obj))
var u = { o : {'name' : 'zs'}, i : 5 } var v = JSON.parse(JSON.stringify(u)) u.o.name = 'ls'; console.log(u,v); // v的o屬性中的name還是'zs'
③ 遞歸( 通用,從底層的角度 ) 基本思想 : 判斷obj 是基本類型就簡單賦值,對象(數組)的話 ,創建一個空[ ](obj是對象)或空{ }(obj是對象),再判斷obj的屬性有沒有對象(數組),有遞歸調用,沒有簡單賦值,直到全部賦值完畢,返回賦值后的new_obj , 看不懂沒關系下面代碼有注釋,絕對可以看懂
var obj = { arr1 : [1,2,3], fn: function(){ console.log('我是一個方法') }, a : '我是普通屬性' } // 現在我要把obj字面量創建里的屬性深拷貝( 屬性值是引用類型也要深拷貝 ) function deepClone(obj){ // 根據類型制造一個新的數組或對象 => 指向一個新的空間 // 由於數組的typeof也是'object',所以用Array.isArray(obj) var new_obj = Array.isArray(obj) ? [] : {}; // 首先判斷obj的類型 // 普通類型 if( typeof obj != 'object' ){ // 這里不能直接返回obj,不然就是淺拷貝的性質 return new_obj = obj } //引用類型 //數組 if(obj instanceof Array ){ for(i = 0; i < obj.length; i++ ){ new_obj[i] = obj[i]; if(typeof new_obj[i] == 'object'){ deepClone(new_obj[i]) } } }else{ //對象 for (let key in obj) { if (obj.hasOwnProperty(key)) { // 對象中的數組和對象 if (typeof obj[key] == 'object') { new_obj[key] = deepClone(obj[key]); }else{//對象中沒有引用類型 new_obj[key] = obj[key] } } } } return new_obj; } var deepClone = deepClone(obj); console.log(deepClone); // 測試是不是深拷貝 obj.fn = '我改變了方法屬性'; console.log(obj); //{arr1: Array(3), fn: ƒ, a: "我是普通屬性", c: "我新增了一個屬性"} console.log(deepClone); // 還是 {arr1: Array(3), fn: ƒ, a: "我是普通屬性"}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
本文原創,僅供學習使用