HOWTO · JavaScript

在 JavaScript 中複製物件

在本文中,我們將看到如何在 JavaScript 中製作物件的副本。

本頁內容

各種程式語言具有各種資料結構,允許你在記憶體中組織和儲存資料。每個資料結構的工作方式都是獨一無二的。例如,在 C++ 和 Java 中,我們有 Hashmap 以鍵值形式儲存資料。同樣,在 JavaScript 中,我們有一個稱為物件的資料結構,它允許你以鍵值格式儲存資料。

在訪問資料時,這些物件會派上用場。我們可以使用物件的鍵輕鬆訪問物件中的任何資料。在本文中,我們將看到在 JavaScript 中複製物件的各種方式。

請注意 JavaScript 物件是可變的,並且儲存為引用。如果你已經建立了一個物件並希望將其分配給其他某個物件,那麼該物件現在將儲存該物件的地址。由於我們將物件的引用儲存在另一個物件中,然後使用這個新物件,我們可以輕鬆地更改原始物件中存在的值。

var a = {'name': 'Adam', 'company': 'Google'}

var b = a;
b.name = 'Sam'

console.log(a.name, b.name);

輸出:

Sam Sam

從上面的示例中可以看出,將一個物件分配給另一個物件不會複製物件本身。它只會將舊物件的地址儲存到新物件中。

在 JavaScript 中有兩種複製物件的方法。一種方式稱為淺拷貝,另一種方式稱為深拷貝。為了實現這些方法,我們可以使用一些 JavaScript 方法,如下所示。

JavaScript 中的淺拷貝物件

在淺拷貝中,只有出現在物件第一層的鍵值對才會被複制到新物件中。並且所有巢狀的元素或屬性,例如陣列或內部的另一個物件,都不會被複制,而是將它們的引用儲存在此物件中。

在淺拷貝中,原始物件的一些屬性也會受到影響。要理解這一點,請看下面的例子。

var obj1 = {
  'firstName': 'James',
  'lastName': 'Bond',
  'films': ['No Time To Die', 'Spectre', 'Skyfall', 'Quantum of Solace'],
  'actors':
      {'characters': {'realName': 'Daniel Craig', 'fakeName': 'James Bond'}}
}

在這個例子中,我們有一個名為 obj1 的物件。要使用 JavaScript 對這個物件進行淺拷貝,我們可以使用 Object.assign() 和擴充套件運算子 ...。讓我們使用 JavaScript 中的以下方法對 obj1 執行淺拷貝。

  1. Object.assign() 方法

Object.assign() 方法有兩個引數。第一個引數是複製完成後將返回的 target 物件。第二個引數是我們要複製的物件:obj1。在我們的例子中,我們將傳遞一個空物件 {} 作為目標。這是因為 obj1 中的所有元素都將被複制到這個空物件中。複製完成後,Object.assign() 將返回我們將儲存在 obj2 變數中的新物件。

var obj2 = Object.assign({}, obj1);

稍後,我們將修改此物件的屬性,我們將實際瞭解為什麼將其稱為淺拷貝。

obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';

console.log(obj1);
console.log(obj2);

輸出:

使用 object.assign() 方法在 javascript 中進行淺拷貝

在這裡,我們使用 obj2、firstNamefilms[] 陣列中的第一部電影和 actors.characters 物件中的 realName 屬性更改三個值。然後我們列印這兩個物件。

上圖顯示兩個物件中只有 firstName 屬性沒有更改。另外兩個屬性 films[]realName 在這兩個物件中都發生了變化。這被稱為淺拷貝,因為 firstName 屬性是唯一的,而其他屬性對於兩個物件都是通用的,因為我們在這裡儲存地址。此處,僅複製存在於第一級的屬性。

  1. 展開運算子 (...)

rest 運算子將把 obj1 的屬性複製到 obj2 中。這類似於 Object.assign(),我們淺拷貝物件的屬性。要使用擴充套件運算子複製物件,你必須在擴充套件符號後寫入物件名稱。

var obj2 = {...obj1};

obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';

你還將獲得我們在使用 Object.assign() 方法後獲得的相同輸出。

深度複製 JavaScript 中的物件

在深度複製中,所有鍵值對都將被複制到新物件中。要執行深度複製,我們可以使用 JSON.parse()JSON.stringify() 方法。請注意,深層複製不會複製原型物件中存在的屬性。

使用 JSON.stringify(),我們將首先將整個物件(在本例中為 obj1)轉換為字串,然後在 JSON.parse() 方法的幫助下,我們將解析將此字串重新轉換為 JSON 格式。

let obj2 = JSON.parse(JSON.stringify(obj1));

在這裡,你可以修改 obj2 內的任何屬性,這不會影響 obj1 內的屬性。

obj2.firstName = 'Camila';
obj2.films[0] = 'abcccc';
obj2.actors.characters.realName = 'Camila';

輸出:

在 javascript 中深度複製一個物件

我們正在修改之前修改的相同值,現在你可以注意到,當我們更改 obj2 的屬性時,它不會影響 obj1 的屬性。