一文掌握 12 个 JS 数组拷贝的妙招,让数据尽在掌控
2024-01-21 06:09:35
穿越 JavaScript 数组拷贝的迷雾
数组是 JavaScript 中用来存储一系列元素的强大数据结构,数组内元素可以具有任意类型,包括其他数组。然而,JavaScript 中的数组是可变的,这意味着在创建数组之后,还可以修改数组的内容。
这乍听起来似乎很好,可以修改数组避免繁琐的重新创建步骤,但是这会导致一个问题:仅仅将一个数组分配给另一个变量并不能实现真正拷贝。两个变量将指向同一个数组,这意味着对其中一个数组的任何更改都会反映在另一个数组上。
举个例子,我们有如下代码:
const originalArray = [1, 2, 3];
const copiedArray = originalArray;
copiedArray.push(4);
console.log(originalArray); // 输出: [1, 2, 3, 4]
如你所见,当修改 copiedArray
时,originalArray
也受到了影响。这是因为 copiedArray
并不是原始数组的副本,而只是指向原始数组的另一个引用。为了真正地复制一个数组,我们需要创建它的一个新副本。
探索 12 个 JS 数组拷贝的实用技巧
- 利用 slice() 方法进行浅拷贝:
const originalArray = [1, 2, 3];
const copiedArray = originalArray.slice();
copiedArray.push(4);
console.log(originalArray); // 输出:[1, 2, 3]
slice()
方法可以创建一个数组的副本,但是它只进行浅拷贝,这意味着它只复制数组的原始值,而不是嵌套的数组或对象。
- 借助 concat() 方法实现浅拷贝:
const originalArray = [1, 2, 3];
const copiedArray = originalArray.concat();
copiedArray.push(4);
console.log(originalArray); // 输出:[1, 2, 3]
concat()
方法也可以创建一个数组的副本,并且它同样只进行浅拷贝。
- 采用扩展运算符展开数组,实现浅拷贝:
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
copiedArray.push(4);
console.log(originalArray); // 输出:[1, 2, 3]
扩展运算符可以快速创建数组的副本,并且它同样只进行浅拷贝。
- 巧用 Array.from() 方法浅拷贝数组:
const originalArray = [1, 2, 3];
const copiedArray = Array.from(originalArray);
copiedArray.push(4);
console.log(originalArray); // 输出:[1, 2, 3]
Array.from()
方法也可以创建数组的副本,并且它同样只进行浅拷贝。
- 通过 JSON.parse() 和 JSON.stringify() 实现深度拷贝:
const originalArray = [1, [2, 3]];
const copiedArray = JSON.parse(JSON.stringify(originalArray));
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
JSON.parse() 和 JSON.stringify() 方法可以实现数组的深度拷贝,这意味着它复制了数组的所有内容,包括嵌套的数组或对象。
- 借助第三方库 lodash 进行深度拷贝:
const originalArray = [1, [2, 3]];
const copiedArray = _.cloneDeep(originalArray);
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
lodash 库提供了 _.cloneDeep()
方法,可以实现数组的深度拷贝。
- 利用递归实现深度拷贝:
function deepCopy(array) {
let copy = [];
for (let i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
copy.push(deepCopy(array[i]));
} else {
copy.push(array[i]);
}
}
return copy;
}
const originalArray = [1, [2, 3]];
const copiedArray = deepCopy(originalArray);
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
这个递归函数可以实现数组的深度拷贝。
- 巧用 map() 方法实现深度拷贝:
function deepCopy(array) {
return array.map(item => {
if (Array.isArray(item)) {
return deepCopy(item);
} else {
return item;
}
});
}
const originalArray = [1, [2, 3]];
const copiedArray = deepCopy(originalArray);
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
这个基于 map() 方法的函数也可以实现数组的深度拷贝。
- 使用 reduce() 方法实现深度拷贝:
function deepCopy(array) {
return array.reduce((copy, item) => {
if (Array.isArray(item)) {
copy.push(deepCopy(item));
} else {
copy.push(item);
}
return copy;
}, []);
}
const originalArray = [1, [2, 3]];
const copiedArray = deepCopy(originalArray);
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
这个基于 reduce() 方法的函数也可以实现数组的深度拷贝。
- 借助 forEach() 方法实现深度拷贝:
function deepCopy(array) {
let copy = [];
array.forEach(item => {
if (Array.isArray(item)) {
copy.push(deepCopy(item));
} else {
copy.push(item);
}
});
return copy;
}
const originalArray = [1, [2, 3]];
const copiedArray = deepCopy(originalArray);
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
这个基于 forEach() 方法的函数也可以实现数组的深度拷贝。
- 巧用 Object.assign() 方法实现浅拷贝:
const originalArray = [1, 2, 3];
const copiedArray = Object.assign([], originalArray);
copiedArray.push(4);
console.log(originalArray); // 输出:[1, 2, 3]
Object.assign()
方法可以实现数组的浅拷贝,但是它不能拷贝嵌套的数组或对象。
- 利用 Array.prototype.map() 方法实现深度拷贝:
const originalArray = [1, [2, 3]];
const copiedArray = originalArray.map(item => {
if (Array.isArray(item)) {
return item.map(i => i);
} else {
return item;
}
});
copiedArray[1].push(4);
console.log(originalArray); // 输出:[1, [2, 3]]
Array.prototype.map()
方法可以实现数组的深度拷贝。
结语
掌握了这些技巧,你就可以轻松地复制和操作数组,从而实现数据的全面掌控。希望本文能对您有所帮助,如果您有其他问题,欢迎随时提问!