這意味着,當您嘗試使用 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 進行序列化和反序列化需要一些時間,是以這不是最快的方法。