在JavaScript 中 14 個(gè)拷貝數(shù)組的技巧
數(shù)組拷貝經(jīng)常被誤解,但這并不是因?yàn)榭截愡^(guò)程本身,而是因?yàn)槿狈?duì) JS 如何處理數(shù)組及其元素的理解。JS 中的數(shù)組是可變的,這說(shuō)明在創(chuàng)建數(shù)組之后還可以修改數(shù)組的內(nèi)容。
這意味著要拷貝一個(gè)數(shù)組,咱們不能簡(jiǎn)單地將舊數(shù)組分配給一個(gè)新變量,它也是一個(gè)數(shù)組。如果這樣做,它們將共享相同的引用,并且在更改一個(gè)變量之后,另一個(gè)變量也將受到更改的影響。這就是我們需要克隆這個(gè)數(shù)組的原因。
接著來(lái)看看一些關(guān)于拷貝何克隆數(shù)組的有趣方法和技巧。
技巧 1 - 使用Array.slice方法
- const numbers = [1, 2, 3, 4, 5]
- const copy = numbers.slice()
- copy.push(6) // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- 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) // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- 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); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 4 - 使用展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- const copy = [...numbers];
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 5 - 使用 Array.of 方法和展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- const copy = Array.of(...numbers);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
Array.of() 方法創(chuàng)建一個(gè)具有可變數(shù)量參數(shù)的新數(shù)組實(shí)例,而不考慮參數(shù)的數(shù)量或類型。Array.of() 和 Array 構(gòu)造函數(shù)之間的區(qū)別在于處理整數(shù)參數(shù):Array.of(7) 創(chuàng)建一個(gè)具有單個(gè)元素 7 的數(shù)組,而 Array(7) 創(chuàng)建一個(gè)長(zhǎng)度為7的空數(shù)組(注意:這是指一個(gè)有7個(gè)空位(empty)的數(shù)組,而不是由7個(gè)undefined組成的數(shù)組)。
- Array.of(7); // [7]
- Array.of(1, 2, 3); // [1, 2, 3]
- Array(7); // [ , , , , , , ]
- Array(1, 2, 3); // [1, 2, 3]
技巧 6 - 使用 Array 構(gòu)造函數(shù)和展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- const copy = new Array(...numbers);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 7 - 使用解構(gòu)
- const numbers = [1, 2, 3, 4, 5];
- const [...copy] = numbers;
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- 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); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 9 - 使用 Array.push 方法和展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- let copy = [];
- copy.push(...numbers);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 10 - 使用 Array.unshift 方法和展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- let copy = [];
- copy.unshift(...numbers);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 11 - 使用 Array.forEach 方法和展開(kāi)操作符
- const numbers = [1, 2, 3, 4, 5];
- let copy = [];
- numbers.forEach((value) => copy.push(value));
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 12 - 使用 for 循環(huán)
- const numbers = [1, 2, 3, 4, 5];
- let copy = [];
- for (let i = 0; i < numbers.length; i++) {
- copy.push(numbers[i]);
- }
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 13 - 使用 Array.reduce 方法
這個(gè)做法是可行,但比較多余,少用
- const numbers = [1, 2, 3, 4, 5];
- const copy = numbers.reduce((acc, x) => { acc.push(x); return acc; }, []);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
技巧 14 - 使用古老的 apply 方法
- let copy = [];
- Array.prototype.push.apply(copy, numbers);
- copy.push(6); // 添加新項(xiàng)以證明不會(huì)修改原始數(shù)組
- console.log(copy);
- console.log(numbers);
- // 輸出
- // [1, 2, 3, 4, 5, 6]
- // [1, 2, 3, 4, 5]
代碼部署后可能存在的BUG沒(méi)法實(shí)時(shí)知道,事后為了解決這些BUG,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具 Fundebug。
原文:https://twitter.com/protic_milos
總結(jié)
請(qǐng)注意,上面這些方法執(zhí)行的是淺拷貝,就是數(shù)組是元素是對(duì)象的時(shí)候,咱們更改對(duì)象的值,另一個(gè)也會(huì)跟著變,就能技巧4來(lái)說(shuō),如果咱們的數(shù)組元素是對(duì)象,如下所示:
- const authors = [
- { name: '前端小智', age: 25 },
- { name: '王大冶', age: 30 },
- ]
- const copy = [...authors ]
- copy[0].name = '被更改過(guò)的前端小智'
- console.log(copy)
- console.log(authors)
輸出
所以上面的技巧適合簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),復(fù)雜的結(jié)構(gòu)要使用深拷貝。數(shù)組拷貝經(jīng)常被誤解,但這并不是因?yàn)榭截愡^(guò)程本身,而是因?yàn)槿狈?duì) JS 如何處理數(shù)組及其元素的理解。