14 個拷貝陣列的 JS 技巧

前端小智發表於2019-11-12

來源:twitter

作用:Milos

譯者:前端小智

你知道的越多,你不知道的越多

點贊再看,養成習慣


本文 GitHub:github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了很多我的文件,和教程資料。歡迎Star和完善,大家面試可以參照考點複習,希望我們一起有點東西。

為了保證的可讀性,本文采用意譯而非直譯。

陣列拷貝經常被誤解,但這並不是因為拷貝過程本身,而是因為缺乏對 JS 如何處理陣列及其元素的理解。JS 中的陣列是可變的,這說明在建立陣列之後還可以修改陣列的內容。

這意味著要拷貝一個陣列,我們們不能簡單地將舊陣列分配給一個新變數,它也是一個陣列。如果這樣做,它們將共享相同的引用,並且在更改一個變數之後,另一個變數也將受到更改的影響。這就是我們需要克隆這個陣列的原因。

接著來看看一些關於拷貝何克隆陣列的有趣方法和技巧。

技巧 1 - 使用Array.slice方法

const numbers = [1, 2, 3, 4, 5]

const copy = numbers.slice()
copy.push(6) // 新增新項以證明不會修改原始陣列

console.log(copy)
console.log(numbers)

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 2 - 使用Array.map方法

const numbers = [1, 2, 3, 4, 5]

const copy = numbers.map( num => num )
copy.push(6) // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 3 - 使用Array.from方法

const numbers = [1, 2, 3, 4, 5];

const copy = Array.from(new Set(numbers));
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 4 - 使用展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = [...numbers];
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 5 - 使用 Array.of 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = Array.of(...numbers);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

Array.of() 方法建立一個具有可變數量引數的新陣列例項,而不考慮引數的數量或型別。Array.of()Array 建構函式之間的區別在於處理整數引數:Array.of(7) 建立一個具有單個元素 7 的陣列,而 Array(7) 建立一個長度為7的空陣列(注意:這是指一個有7個空位(empty)的陣列,而不是由7undefined組成的陣列)。

Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]
複製程式碼

技巧 6 - 使用 Array 建構函式和展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = new Array(...numbers);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 7 - 使用解構

const numbers = [1, 2, 3, 4, 5];

const [...copy] = numbers;
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 8 - 使用 Array.concat 方法

const numbers = [1, 2, 3, 4, 5];

const copy = numbers.concat();
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 9 - 使用 Array.push 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
copy.push(...numbers);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 10 - 使用 Array.unshift 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
copy.unshift(...numbers);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 11 - 使用 Array.forEach 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
numbers.forEach((value) => copy.push(value));
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 12 - 使用 for 迴圈

const numbers = [1, 2, 3, 4, 5];

let copy = [];
for (let i = 0; i < numbers.length; i++) {
    copy.push(numbers[i]);
}
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 13 - 使用 Array.reduce 方法

這個做法是可行,但比較多餘,少用

const numbers = [1, 2, 3, 4, 5];

const copy = numbers.reduce((acc, x) => { acc.push(x); return acc; }, []);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

技巧 14 - 使用古老的 apply 方法

const numbers = [1, 2, 3, 4, 5];

let copy = [];
Array.prototype.push.apply(copy, numbers);
copy.push(6); // 新增新項以證明不會修改原始陣列

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]
複製程式碼

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:twitter.com/protic_milo…

總結

請注意,上面這些方法執行的是淺拷貝,就是陣列是元素是物件的時候,我們們更改物件的值,另一個也會跟著變,就能技巧4來說,如果我們們的陣列元素是物件,如下所示:

const authors = [
  { name: '前端小智', age: 25 }, 
  { name: '王大冶', age: 30 }, 
]

const copy = [...authors ]
copy[0].name = '被更改過的前端小智'

console.log(copy)
console.log(authors)
複製程式碼

輸出

14 個拷貝陣列的 JS 技巧

所以上面的技巧適合簡單的資料結構,複雜的結構要使用深拷貝。陣列拷貝經常被誤解,但這並不是因為拷貝過程本身,而是因為缺乏對 JS 如何處理陣列及其元素的理解。

交流(歡迎加入群,群工作日都會發紅包,互動討論技術)

乾貨系列文章彙總如下,覺得不錯點個Star,歡迎 加群 互相學習。

github.com/qq449245884…

因為篇幅的限制,今天的分享只到這裡。如果大家想了解更多的內容的話,可以去掃一掃每篇文章最下面的二維碼,然後關注我們們的微信公眾號,瞭解更多的資訊和有價值的內容。

14 個拷貝陣列的 JS 技巧

相關文章