JavaScript 中数组克隆

Posted by cl9000 on June 19, 2020

万物皆有其美,但并非人人都能发现。——<安迪.沃霍尔>

作者:Ashish Lahoti
译者:cl9000
来源:https://codingnconcepts.com/javascript/how-to-clone-array-in-javascript/

在本教程中,我们将学习如何在 JavaScript 中克隆一个数组,并学习数组的 浅拷贝深拷贝 之间的区别。

以下是克隆数组的不同方法的快速视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** Shallow Copy */
const fruits = ['apple', 'banana', 'mango'];

// 1. ES6 Spread Operator
[...fruits];

// 2. Array.slice
fruits.slice();

// 3. Array.from
Array.from(fruits);

/** Deep Copy */
const grocery = [['apple', 'banana', 'mango'],
['onion', 'potato', 'tomato'],
['milk', 'juice']];

// 1. JSON.stringify & JSON.parse
JSON.parse(JSON.stringify(grocery));

// 2. map
grocery.map(element => [...element]);

1. 浅拷贝

我们将研究在 JavaScript 中创建数组的 浅拷贝 的各种方法。浅拷贝 意味着第一层被复制,而深层被 引用

当你处理一维数组时,浅拷贝 就足够好了。让我们看看使用浅拷贝复制数组的不同方法:

1.1 ES6 扩展运算符

如果您已开始使用 ES6,则建议使用 **扩展运算符(…)**在 JavaScript 中克隆一个数组。简短的语法非常方便。

1
2
3
const fruits = ['apple', 'banana', 'mango'];
const cloneFruits = [...fruits];
// ['apple', 'banana', 'mango']

1.2 Array.slice()

如果您仍在使用旧方法,则 Array.slice 可以用来克隆数组:

1
2
3
const fruits = ['apple', 'banana', 'mango'];
const cloneFruits = fruits.slice();
// ['apple', 'banana', 'mango']

1.3 Array.from()

我们还可以使用 Array.from 方法克隆一个数组:

1
2
3
const fruits = ['apple', 'banana', 'mango'];
const cloneFruits = Array.from(fruits);
// ['apple', 'banana', 'mango']

浅拷贝问题

让我们看一下浅拷贝在多维(嵌套)数组中的行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const fruits  = ['apple', 'banana', 'mango'];
const veggies = ['onion', 'potato', 'tomato'];
const liquids = ['milk', 'juice'];

const grocery = [fruits, veggies, liquids];
const groceryCopy = [...grocery];

grocery[2].push('beer');

console.log(grocery);
console.log(groceryCopy);
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice', 'beer']]
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice', 'beer']]
// They've both been changed because they share references

我们看到 Array及其浅表副本都已更改,因为它们共享了引用。请记住,更浅层次的副本引用了更深层次的内容。

3. 深拷贝

我们可以使用 深拷贝 来解决多维(嵌套)数组的浅层复制产生的问题。让我们看一下使用深拷贝克隆数组的不同方法:

3.1 JSON.stringify()和JSON.parse()

我们可以利用 JSON.stringifyJSON.parse 的结合,实现数组的 深拷贝

  • JSON.stringify 将一个对象变成一个字符串。
    JSON.parse 将字符串转换为对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const fruits  = ['apple', 'banana', 'mango'];
const veggies = ['onion', 'potato', 'tomato'];
const liquids = ['milk', 'juice'];

const grocery = [fruits, veggies, liquids];
const groceryCopy = JSON.parse(JSON.stringify(grocery));

grocery[2].push('beer');

console.log(grocery);
console.log(groceryCopy);
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice', 'beer']]
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice']]
// These two arrays are completely separate!

3.2 Array.map ()

您还可以通过迭代和使用 Array.map 在更深层次上创建多维(嵌套)数组的深层副本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const fruits  = ['apple', 'banana', 'mango'];
const veggies = ['onion', 'potato', 'tomato'];
const liquids = ['milk', 'juice'];

const grocery = [fruits, veggies, liquids];
const groceryCopy = grocery.map(element => [...element]);

grocery[2].push('beer');

console.log(grocery);
console.log(groceryCopy);
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice', 'beer']]
// (3) [['apple', 'banana', 'mango'], ['onion', 'potato', 'tomato'], ['milk', 'juice']]
// These two arrays are completely separate!

请注意,上面的示例对二维数组进行了深拷贝。如果 Array 具有更多的嵌套级别,则需要进行更深的迭代。

参考

关注【公众号】,了解更多。
关注【公众号】,了解更多。
关注【公众号】,了解更多。



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!