來源: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)的陣列,而不是由7
個undefined
組成的陣列)。
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。
總結
請注意,上面這些方法執行的是淺拷貝,就是陣列是元素是物件的時候,我們們更改物件的值,另一個也會跟著變,就能技巧4來說,如果我們們的陣列元素是物件,如下所示:
const authors = [
{ name: '前端小智', age: 25 },
{ name: '王大冶', age: 30 },
]
const copy = [...authors ]
copy[0].name = '被更改過的前端小智'
console.log(copy)
console.log(authors)
複製程式碼
輸出
所以上面的技巧適合簡單的資料結構,複雜的結構要使用深拷貝。陣列拷貝經常被誤解,但這並不是因為拷貝過程本身,而是因為缺乏對 JS 如何處理陣列及其元素的理解。
交流(歡迎加入群,群工作日都會發紅包,互動討論技術)
乾貨系列文章彙總如下,覺得不錯點個Star,歡迎 加群 互相學習。
因為篇幅的限制,今天的分享只到這裡。如果大家想了解更多的內容的話,可以去掃一掃每篇文章最下面的二維碼,然後關注我們們的微信公眾號,瞭解更多的資訊和有價值的內容。