JavaScript >> Javascript 文檔 >  >> Tags >> Arrays

在 JavaScript 中克隆數組

在我之前的一篇文章中,我介紹瞭如何在 JavaScript 中復制對象。複製對像是一項相當複雜的工作,因為您還必須能夠複製對像中可能存在的所有其他數據類型。但如果你只是 複製數組?與上一篇文章一樣,有很多方法可以執行此任務,我將在本文中介紹其中的一些。

但首先,請注意速度。雖然這對於所有應用程序可能並不重要,但如果復制大型數組是代碼中的常見操作,或者速度是否真的很重要,則需要考慮這一點。對於下面的一些方法,我注意到它相對於其他方法的速度,這是來自這個基準測試的結果。

複製簡單數組

對於第一部分,我們假設您要復制的數組僅包含原始(和不可變)數據類型。也就是說,數組只包含數字、布爾值、字符串等。這樣我們可以更專注於從一個數組到另一個數組的數據傳輸,而不是我們如何處理複製數組的實際內容,我將請參閱下面的“深拷貝”部分。

複製數組的方法數量驚人,其中包括:

  • push
  • 傳播
  • slice
  • Array.from
  • _.clone

擴展運算符和 slice 方法是複制淺數組的最快方法,但請記住,這確實取決於底層運行時,因此可能並非普遍適用。

推送

這可能是最明顯的解決方案,它遍歷原始數組並使用新數組的 push() 將元素從一個數組添加到另一個數組的方法:

let oldArr = [3, 1, 5, 2, 9];
let newArr = [];
for (let i=0; i < oldArr.length; i++) {
    newArr.push(oldArr[i]);
}

我們只需遍歷要復制的數組並將每個元素推送到新數組。

傳播

此方法使用擴展運算符,該運算符在 ES6 中定義,可在大多數最新瀏覽器中使用。

它的工作原理如下:

let oldArr = [3, 1, 5, 2, 9];
let newArr = [...oldArr];

如果我要使用原生解決方案而不使用第三方庫,那麼這通常是我更喜歡的解決方案,因為它的語法簡潔明了。

一個重要的注意事項是,這種複制只適用於頂層(就像許多這些方法一樣),因此如果您需要任何東西的深層副本,則不應使用它。

切片

slice() 方法通常用於返回數組的一部分,由 beginning 指定 和 end 參數。但是,如果沒有傳遞參數,則返回整個數組的副本:

let oldArr = [3, 1, 5, 2, 9];
let newArr = oldArr.slice();

在許多 JavaScript 運行時,這是複制數組的最快方式。

Array.from

Array.from 方法旨在創建任何 iterable 的淺表副本 你傳遞給它,它還需要一個可選的映射函數作為第二個參數。所以它可以用來創建一個由字符串、集合、映射,當然還有其他數組組成的數組:

let oldArr = [3, 1, 5, 2, 9];
let newArr = Array.from(oldArr);

Lodash 克隆

如果您閱讀了這篇關於復制對象的文章,您可能對 Lodash 的 clone() 和 cloneDeep() 方法很熟悉。這些方法完全符合您的預期 - 傳遞給它的任何對象(或數組、原語等)都將被複製並返回。

_.cloneDeep (下面進一步描述)不同之處在於它不會在頂層停止克隆,它會遞歸複製它在任何級別遇到的所有對象。

鑑於此,我們也可以使用它來複製數組:

let oldArr = [3, 1, 5, 2, 9];
let newArr = _.clone(oldArr);

_.clone 與其他方法相比,性能非常好,因此如果您已經在應用程序中使用此庫,那麼這是一個簡單的解決方案。

深拷貝

需要指出的重要一點是,上述所有方法都只執行數組的淺拷貝。因此,如果你有一個對像數組,例如,實際數組將被複製,但底層對象將通過引用傳遞給新數組。

為了演示這個問題,我們來看一個例子:

let oldArr = [{foo: 'bar'}, {baz: 'qux'}];
let newArr = [...oldArr];
console.log(newArr === oldArr);
console.log(newArr[0] === oldArr[0]);
false
true

在這裡您可以看到,雖然實際數組是新的,但其中的對象卻不是。對於某些應用程序,這可能是一個大問題。如果這適用於您,那麼這裡有一些其他方法可以嘗試。

Lodash 克隆深度

Lodash 的 _.cloneDeep 方法的作用與 _.clone() 完全相同 ,除了它遞歸地克隆你傳遞給它的數組(或對象)中的所有內容。使用與上面相同的示例,我們可以看到使用 _.cloneDeep() 將為我們提供一個新數組 複製的數組元素:

const _ = require('lodash');

let oldArr = [{foo: 'bar'}, {baz: 'qux'}];
let newArr = _.cloneDeep(oldArr);
console.log(newArr === oldArr);
console.log(newArr[0] === oldArr[0]);
false
false

JSON 方法

JavaScript 確實提供了一些方便的 JSON 方法來處理將大多數 JS 數據類型轉換為字符串,然後將有效的 JSON 字符串轉換為 JS 對象。各自的使用方法如下:

let oldArr = [{foo: 'bar'}, {baz: 'qux'}];
let arrStr = JSON.stringify(oldArr);
console.log(arrStr);

let newArr = JSON.parse(arrStr);
console.log(newArr);

console.log(newArr === oldArr);
console.log(newArr[0] === oldArr[0]);

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

'[{"foo":"bar"},{"baz":"qux"}]'
[ { foo: 'bar' }, { baz: 'qux' } ]
false
false

這種方法效果很好,並且不需要任何第三方庫。但是,有兩個主要問題:

  • 數據必須可通過 JSON 序列化和反序列化
  • 以這種方式使用 JSON 方法比其他解決方案慢得多

因此,如果您有無法序列化為 JSON 的數據,或者如果速度對您的應用程序很重要,那麼這對您來說可能不是一個好的解決方案。

結論

在本文中,我介紹了在 JavaScript 中復制數組的多種方法,既可以使用本機代碼,也可以使用 Lodash 中有用的第三方庫。我們還研究了深度克隆數組的問題以及存在哪些解決方案來解決它。

是否有其他方法最適合您?請在評論中告訴我們您的想法。


Tutorial JavaScript 教程
  1. 面向前端 Web 開發人員的技術原型工具和庫 💻🚀🌐

  2. 不要讓我思考! |編寫代碼時將開發人員體驗放在首位的 4 種方法

  3. #JavaScript 2019#ES 中的新功能

  4. 作為前端開發人員學習 AWS

  5. for..in 循環和 Object.keys 不同的行為

  6. 保存 React Hook 備忘單

  7. 如何使 DIV 無法聚焦?

  1. Web Inspector 和 Firefox Dollar 功能

  2. 確保內容腳本可以看到 `click` 事件

  3. JavaScript 教程:如何使用數組方法

  4. 使用 JavaScript new Array(n) 聲明

  5. 如何使用 JavaScript 模擬鼠標點擊?

  6. JavaScript 基礎錯誤處理

  7. 為 Docker API 構建 GraphQL 包裝器

  1. 將 Blitz.js 應用程序部署到 Vercel

  2. 作為 Peloton 的前端開發人員,我所學到的規劃和構建 MVP

  3. 2019 年夏季培養程序員訓練營

  4. 如何在 React 應用程序中創建集成測試