前言
所謂深複製與淺複製(深拷貝與淺拷貝),乍一聽感覺聽高大上,像是乙個非常難理解的概念,其實我們平常專案開發都是在用的,只是你可能不知道該怎麼叫它的名字而已,就像你聽熟了一首歌,就是不知道這首歌叫什麼名字一樣。
在j**ascript中有兩種資料型別,一種是基本型別,另一種是引用型別,今天說討論的深複製與淺複製就是和這兩種資料型別有直接的關係。
1、基本型別的複製
js種的基本型別有number boolean string undefined null這五類,在宣告的時候,基本型別的資料都是存放在棧記憶體中,如下圖:
首先宣告的a變數會儲存在棧記憶體裡,然後又在棧記憶體裡複製了乙個a並且賦值給b,此時棧記憶體裡彙總新分配乙個記憶體給不,a和b的值都是abc;然後給b重新賦值,由於a和b都是獨立存在的兩個變數,所以兩個值任何乙個變化,都不會影響另外乙個變數的值;通俗點來說,就是你有乙個叫做a的word文件,原本在d盤裡,你把它複製了乙份仍在了桌面上,這個時候你對兩個檔案的編輯並不會相互影響,如上圖。
2、引用型別的複製
引用型別,即object,function的值都是存在堆記憶體中,棧記憶體中通過指標指向這個值在堆中的位址,而對於引用型別來說普通的賦值操作只是將指標的位址複製了乙份給新的變數,屬於淺複製,如下圖:
這裡將arr賦值給arr1,其實就是複製了arr的指標,所以arr1的指向位址和arr是一樣的,這樣不管操作arr還是arr1都會改變堆中陣列的值,列印arr或者arr1都是改變後的值,這種情況只是改變了指標的指向,還用檔案複製的形式來解釋的話就是複製了乙個檔案的快捷方式,把它仍在桌面上,開啟的仍然是原始檔,如上圖。
但是現在有乙個需求,就是後台請求過來的json物件,在對其處理之前需要拷貝乙份以方便其他開發人員再開發,如果我們用上面的賦值方式複製乙份出來肯定是不行的,這樣的話你下面對資料的處理也會改變源資料的值,那應該怎麼處理呢?看下面**
1這樣基於重新複製了乙份資料出來,而且下面如果你對複製出來的資料進行修改,也不會影響源資料function
copy(obj)
3for(var key in
obj)
6return
tobj7}
89var obj =;
13var obj1 =copy(obj);
14 obj1.name = "mrbone"
15 console.log(obj.name) //
"mrgao"
16 console.log(obj1.name) //
"mrbone"
但是,如果出現下面這種情況還是會有問題
1如此看來,值還是都改變了,上面兩者只是obj中多了乙個skill物件而已,由於遍歷複製的只是obj中的屬性,所以obj.skill作為乙個引用型別物件,也只是複製了乙個指標過去,所以當obj1中的skill發生了變化,obj中的skill也會變化,那麼如何解決這個問題呢?var obj =8};
9function
copy(obj)
11for(var key in
obj)
14return
tobj15}
16var obj1 =copy(obj);
17 obj1.skill.work = "j**a"
18 console.log(obj.skill.work) //
j**a
19 console.log(obj1.skill.work) //
j**a
1為了方便理解,這裡只考慮到傳入的值為obj,如此,當遍歷到key的值為'object'型別時,這遞迴呼叫本方法,來完成對內層物件的複製。var obj =8};
9function
copy(obj)
11for(var key in
obj) else17}
18return
tobj19}
20var obj1 =copy(obj);
21 obj1.skill.work = "j**a"
22 console.log(obj.skill.work) //
j**ascript
23 console.log(obj1.skill.work) //
j**a
除了上面這種方法外,還有一種方法可以實現深複製
1這種方法為先將obj轉化為字串,複製的時候就會重新在棧記憶體中複製乙份,然後json.parse之後重新賦值給obj1,就實現了對物件的深複製。var obj =8};
9var obj1 = json.parse(json.stringify(obj)); //
先將obj轉為字串再複製
10 obj1.skill.work = "j**a"
11 console.log(obj.skill.work) //
j**ascript
12 console.log(obj1.skill.work) //
j**a
總結淺複製:之前理解的是淺複製指的是對引用物件指標的複製,並沒有複製其本質內容;後來對淺複製的理解為對引用物件一層複製為淺複製,而對應的深複製為以上兩種對物件進行深複製的方法。
深複製:深複製就是對乙個物件通過遞迴,或型別轉換的全面複製。
對於以上純屬個人理解,如有紕漏,歡迎指正!
js中的深複製與淺複製
二者的區別 深複製只複製物件的值,在複製後指向不同的位址,但兩個物件的值相同 淺複製複製的是物件的位址,在複製後指向同乙個位址,兩個物件的位址與值都相同 淺複製 let a let b a console.log a console.log b 如果改變b的name屬性,會發現a的name屬性也會改...
js深複製淺複製
深淺複製主要是針對於js的引用資料型別的,因為他們不只一層,並且修改乙個變數是不希望修改到另外乙個變數。淺複製 只複製指向某個物件的指標,新舊物件共享一塊記憶體,修改新物件會改到原物件上。深複製 不共享記憶體,修改新物件不會改到原物件上。淺複製實現 js 簡單的賦值操作一般實現的都是淺複製。深複製實...
淺複製與深複製
舉個複製 的例子 function clone p,s for var prop in p return s var a var b clone a,b b.hobby 1 reading b.hobby 1 reading c.hobby 1 reading 由上面的例子可以看出,當執行淺複製時,...