深入理解JavaScript之深淺複製

千鋒IT教育發表於2023-03-07

在JavaScript中,深淺複製都是對物件或陣列進行復制,以便在對原始物件進行更改時不會影響到已複製的物件。淺複製只複製物件的一層,而深複製會複製整個物件的所有層次。

使用場景

1. 表單資料處理

在前端開發中,表單處理是一個非常常見的場景。當使用者在表單中輸入資料時,我們需要將這些資料儲存到一個物件中,然後將物件傳送到伺服器。但是,由於表單中可能包含巢狀的物件和陣列,因此我們需要使用深複製來複制整個表單資料,確保資料完整無誤地傳送到伺服器上。

2. Redux 狀態管理

在使用 Redux 進行狀態管理時,由於 Redux 的狀態通常是一個物件或包含物件的陣列,因此深複製也經常會用到。在 Redux 中,當我們需要修改狀態時,我們通常會複製整個狀態物件,然後對副本進行修改,以避免修改原始狀態。使用深複製可以確保我們複製的狀態物件是完全獨立的,從而保持應用程式的穩定性和可維護性。

3. 物件的快取和比較

在前端開發中,當我們需要快取某些物件時,我們需要使用深複製來複制物件並將其儲存在快取中。這樣可以確保快取中的物件與原始物件完全獨立,從而避免意外的修改。此外,當我們需要比較兩個物件是否相等時,也可以使用深複製來比較它們的值,以避免引用相等和值相等的混淆。

4. 資料結構的變換

在前端開發中,有時我們需要對一個複雜的資料結構進行變換,例如將一個巢狀的物件轉換為陣列或將一個陣列轉換為巢狀的物件。在這種情況下,我們可以使用深複製來複制原始資料,並使用適當的演演算法對副本進行變換,以避免修改原始資料。

總之,在前端開發中,深複製是非常常見的場景,可以幫助我們處理複雜的資料結構,並保持程式碼的穩定性和可維護性。

淺複製

淺複製是對物件或陣列進行淺層複製,只複製物件的一層屬性,當複製的物件中有引用型別的屬性時,複製出來的物件和原物件會共享引用型別的屬性。這意味著,如果原物件中的引用型別屬性被修改,複製出來的物件也會受到影響。因此,淺複製只適用於一些簡單的資料型別的物件。

以下是實現淺複製的幾種方式:

1. Object.assign()

Object.assign() 方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。返回目標物件。Object.assign() 會覆蓋目標物件中與源物件屬性名相同的屬性值。透過傳入一個空物件,可以很容易地實現淺複製。

const obj = { a: 1, b: 2 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1, b: 2 }

2. Spread operator

Spread operator 可以將一個物件或陣列展開為多個引數,也可以用於淺複製。透過展開一個物件,可以將其屬性複製到新的物件中。

const obj = { a: 1, b: 2 };
const copy = { ...obj };
console.log(copy); // { a: 1, b: 2 }

3. Array.slice()

Array.slice() 方法返回一個從開始索引到結束索引(不包括結束索引)的新陣列。如果不傳入任何引數,將返回一個原陣列的淺複製。可以使用該方法對陣列進行淺複製。

const arr = [1, 2, 3];
const copy = arr.slice();
console.log(copy); // [1, 2, 3]

4. Array.concat()

Array.concat() 方法用於將一個或多個陣列與原陣列合並,並返回新的陣列。如果不傳入任何引數,將返回一個原陣列的淺複製。可以使用該方法對陣列進行淺複製。

const arr = [1, 2, 3];
const copy = [].concat(arr);
console.log(copy); // [1, 2, 3]

深複製

深複製是對物件或陣列進行遞迴複製,複製整個物件的所有層次,這樣就可以避免物件中的引用型別的屬性共享的問題。深複製可以完全複製原始物件,並生成一個新的獨立的物件。但是,深複製的效能比淺複製要

以下是實現深複製的幾種方式:

1. JSON.parse() 和 JSON.stringify()

可以使用 JSON.parse() 和 JSON.stringify() 方法實現深複製。透過將原物件轉換為 JSON 字串,然後將其再轉換回物件,可以實現一個新的獨立的物件。

const obj = { a: { b: 1 } };
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy); // { a: { b: 1 } }

但是,需要注意的是,這種方法只能用於序列化可以轉換為 JSON 的資料型別,例如物件、陣列、字串、數字、布林值和 null。不能用於序列化函式、正規表示式和日期等非 JSON 標準的資料型別。而且,這種方法也不能處理迴圈引用的物件,因為 JSON.stringify() 在處理迴圈引用時會丟擲異常。

2. 遞迴實現

遞迴是實現深複製的一種常用方法。遞迴可以在物件或陣列的每一層進行復制,並生成一個新的獨立的物件。可以使用 typeof 運運算元來判斷一個屬性是不是一個物件或陣列,如果是,則對其進行遞迴複製。

function deepCopy(obj) {
 if (typeof obj !== 'object' || obj === null) {
 return obj;
 }
 const copy = Array.isArray(obj) ? [] : {};
  Object.keys(obj).forEach(key => {
    copy[key] = deepCopy(obj[key]);
 });
 return copy;
}
const obj = { a: { b: 1 } };
const copy = deepCopy(obj);
console.log(copy); // { a: { b: 1 } }

深淺複製是 JavaScript 中常用的操作,用於複製物件和陣列。淺複製只複製物件的一層,而深複製會複製整個物件的所有層次。淺複製的實現方式有 Object.assign()、Spread operator、Array.slice() 和 Array.concat(),而深複製的實現方式有 JSON.parse() 和 JSON.stringify() 和遞迴實現。需要根據具體的場景選擇適合的方法。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70023145/viewspace-2938540/,如需轉載,請註明出處,否則將追究法律責任。

相關文章