天天看點

如何在javascript中複制/克隆數組

作者:豆豆媽超厲害
如何在javascript中複制/克隆數組

這意味着,當您嘗試使用 const newArray = oldArray 複制它時,它将複制對原始數組的引用而不是複制值。

const beers = ['', '', ''];
const beersCopy = beers;
console.log(beers === beersCopy);
// The console output will be true, because it's pointing to the exact value in memory.
           

淺拷貝數組

當拷貝或克隆數組時,值的資料類型是決定使用何種方法的關鍵。

如果您的數組僅包含原始不可變值(數字、布爾值、字元串等),您可以使用以下方法。

  • push
  • … (傳播)
  • .slice -Array.from
  • _.clone (lodash) .push() 一種經典的數組方法,也是最明顯的方法,基本上循環原始數組并使用 push() 方法将原始數組中的元素推送到新數組中。

我們簡單地周遊原始數組并将每個元素推送到新數組。

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

…(展開)

展開運算符是最快的方法之一,是在 ES6 中引入的。它簡潔明了,是一種本地方法(對不起 lodash)。

const arr = [1, 2, 3];
const newArr = [...arr];
.slice()
           

slice() 方法将數組的一部分的淺拷貝傳回到從頭到尾選擇的新數組對象中 arr.slice([start[, end]])。原始數組不會被修改。這是複制數組的最快方法。

const arr = [1, 2, 3];
const newArr = arr.slice();
Array.from
           

Array.from() 靜态方法從類數組或可疊代對象(Map 或 Set)建立一個新的淺拷貝 Array 執行個體。

它還采用可選的映射函數作為第二個參數 Array.from(arrayLike [, mapFn [, thisArg]])。

const arr = [1, 2, 3];
const newArr = Array.from(arr);
_.clone()
           

lodash 的 _.clone(value) 方法建立了一個值的淺克隆。它表現良好,如果您已經在您的應用程式中使用 lodash,它是一個可行的選擇。

// import lodash
const _ = require('lodash');
const arr = [1, 2, 3];
const newArr = _.clone(arr);
Deep Copy Arrays
           

上面的所有方法都會建立數組的淺表副本。如果您将對象作為數組項,并且嘗試進行淺拷貝,則将複制實際數組,但底層對象将通過引用傳遞給新數組。

讓我們通過一個代碼示例來看一下這個問題。

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];
const arrCopy = [...arr];
console.log(arr === arrCopy);
           

// 這将傳回 false,因為數組已被複制(淺複制),記憶體中的新引用。

console.log(arr[0] === arrCopy[0]);

// 這将傳回 true,因為引用指向記憶體中的相同位置。

有幾種方法可以建立深度克隆。

jQuery.extend()

_.clonedeep()

JSON (stringify/parse)

jQuery.extend()

如果您仍在項目中使用 jQuery,則可以使用 jQuery 的擴充方法。

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];
const arrCopy = jQuery.extend(true, [], arr);
console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
_.cloneDeep()
           

來自 Lodash 的方法 _.cloneDeep(value) 做的事情與 _.clone() 完全相同,除了它遞歸地克隆數組中的所有内容。

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];
// import lodash
const _ = require('lodash');
const arrCopy = _.cloneDeep(arr);
console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
           

JSON 方法

JavaScript 提供了用于序列化和反序列化的原生方法,基本上是将大多數資料類型轉換為 JSON 字元串,然後将有效的 JSON 字元串轉換為對象。

它可以這樣使用:

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];
const arrCopy = JSON.parse(JSON.stringify(arr));
console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).
console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.
           

使用這種方法有一些優點和缺點。一個優點是它不需要像 Lodash 這樣的第三方庫。缺點是提供的數組資料需要可序列化,通過 JSON 進行序列化和反序列化需要一些時間,是以這不是最快的方法。