深淺拷貝
●?在 JavaScript 中,深淺拷貝都是對對象或數(shù)組進行復制,以便在對原始對象進行更改時不會影響到已復制的對象。淺拷貝只復制對象的一層,而深拷貝會復制整個對象的所有層次。
使用場景
1.? 表單數(shù)據(jù)處理
在前端開發(fā)中,表單處理是一個非常常見的場景。當用戶在表單中輸入數(shù)據(jù)時,我們需要將這些數(shù)據(jù)保存到一個對象中,然后將對象發(fā)送到服務(wù)器。但是,由于表單中可能包含嵌套的對象和數(shù)組,因此我們需要使用深拷貝來復制整個表單數(shù)據(jù),確保數(shù)據(jù)完整無誤地發(fā)送到服務(wù)器上。
2.? Redux 狀態(tài)管理
在使用 Redux 進行狀態(tài)管理時,由于 Redux 的狀態(tài)通常是一個對象或包含對象的數(shù)組,因此深拷貝也經(jīng)常會用到。在 Redux 中,當我們需要修改狀態(tài)時,我們通常會復制整個狀態(tài)對象,然后對副本進行修改,以避免修改原始狀態(tài)。使用深拷貝可以確保我們復制的狀態(tài)對象是完全獨立的,從而保持應(yīng)用程序的穩(wěn)定性和可維護性。
3.? 對象的緩存和比較
在前端開發(fā)中,當我們需要緩存某些對象時,我們需要使用深拷貝來復制對象并將其存儲在緩存中。這樣可以確保緩存中的對象與原始對象完全獨立,從而避免意外的修改。此外,當我們需要比較兩個對象是否相等時,也可以使用深拷貝來比較它們的值,以避免引用相等和值相等的混淆。
4.? 數(shù)據(jù)結(jié)構(gòu)的變換
在前端開發(fā)中,有時我們需要對一個復雜的數(shù)據(jù)結(jié)構(gòu)進行變換,例如將一個嵌套的對象轉(zhuǎn)換為數(shù)組或?qū)⒁粋€數(shù)組轉(zhuǎn)換為嵌套的對象。在這種情況下,我們可以使用深拷貝來復制原始數(shù)據(jù),并使用適當?shù)乃惴▽Ω北具M行變換,以避免修改原始數(shù)據(jù)。
●?總之,在前端開發(fā)中,深拷貝是非常常見的場景,可以幫助我們處理復雜的數(shù)據(jù)結(jié)構(gòu),并保持代碼的穩(wěn)定性和可維護性。
淺拷貝
●?淺拷貝是對對象或數(shù)組進行淺層復制,只復制對象的一層屬性,當復制的對象中有引用類型的屬性時,復制出來的對象和原對象會共享引用類型的屬性。這意味著,如果原對象中的引用類型屬性被修改,復制出來的對象也會受到影響。因此,淺拷貝只適用于一些簡單的數(shù)據(jù)類型的對象。
●?以下是實現(xiàn)淺拷貝的幾種方式:
1.? Object.assign()
●?Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。返回目標對象。Object.assign() 會覆蓋目標對象中與源對象屬性名相同的屬性值。通過傳入一個空對象,可以很容易地實現(xiàn)淺拷貝。
2.? Spread operator
●?Spread operator 可以將一個對象或數(shù)組展開為多個參數(shù),也可以用于淺拷貝。通過展開一個對象,可以將其屬性復制到新的對象中。
3.? Array.slice()
●?Array.slice() 方法返回一個從開始索引到結(jié)束索引(不包括結(jié)束索引)的新數(shù)組。如果不傳入任何參數(shù),將返回一個原數(shù)組的淺拷貝??梢允褂迷摲椒▽?shù)組進行淺拷貝。
4.? Array.concat()
●?Array.concat() 方法用于將一個或多個數(shù)組與原數(shù)組合并,并返回新的數(shù)組。如果不傳入任何參數(shù),將返回一個原數(shù)組的淺拷貝。可以使用該方法對數(shù)組進行淺拷貝。
深拷貝
●?深拷貝是對對象或數(shù)組進行遞歸復制,復制整個對象的所有層次,這樣就可以避免對象中的引用類型的屬性共享的問題。深拷貝可以完全復制原始對象,并生成一個新的獨立的對象。但是,深拷貝的性能比淺拷貝要
●?以下是實現(xiàn)深拷貝的幾種方式:
1.? JSON.parse() 和 JSON.stringify()
●?可以使用 JSON.parse() 和 JSON.stringify() 方法實現(xiàn)深拷貝。通過將原對象轉(zhuǎn)換為 JSON 字符串,然后將其再轉(zhuǎn)換回對象,可以實現(xiàn)一個新的獨立的對象。
●?但是,需要注意的是,這種方法只能用于序列化可以轉(zhuǎn)換為 JSON 的數(shù)據(jù)類型,例如對象、數(shù)組、字符串、數(shù)字、布爾值和 null。不能用于序列化函數(shù)、正則表達式和日期等非 JSON 標準的數(shù)據(jù)類型。而且,這種方法也不能處理循環(huán)引用的對象,因為 JSON.stringify() 在處理循環(huán)引用時會拋出異常。
2.? 遞歸實現(xiàn)
●?遞歸是實現(xiàn)深拷貝的一種常用方法。遞歸可以在對象或數(shù)組的每一層進行復制,并生成一個新的獨立的對象??梢允褂?typeof 操作符來判斷一個屬性是不是一個對象或數(shù)組,如果是,則對其進行遞歸復制。
深淺拷貝是 JavaScript 中常用的操作,用于復制對象和數(shù)組。淺拷貝只復制對象的一層,而深拷貝會復制整個對象的所有層次。淺拷貝的實現(xiàn)方式有 Object.assign()、Spread operator、Array.slice() 和 Array.concat(),而深拷貝的實現(xiàn)方式有 JSON.parse() 和 JSON.stringify() 和遞歸實現(xiàn)。需要根據(jù)具體的場景選擇適合的方法。