作者:Yazeed Bzadough
译者:allen
JavaScript 有很多方法可以做任何事情,现在我们研究数组。
1.扩展运算符(浅拷贝)
自从 ES6 发布以来,这一直是最受欢迎的方法。这是一个简短的语法,你会发现它在使用像 React 和 Redux 这样的库时非常有用。
numbers = [1, 2, 3];
numbersCopy = [...numbers];
注意:这不能安全地复制多维数组。数组/对象值通过引用而不是按值复制。
这可以
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
这不可以
nestedNumbers = [[1], [2]];
numbersCopy = [...nestedNumbers];
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
2.for 循环(浅拷贝)
由于我们的圈子中流行的函数式编程,使得这种方法最不受欢迎
numbers = [1, 2, 3];
numbersCopy = [];
for (i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}
注意:这不能安全地复制多维数组。由于你使用的是=运算符,因此它将通过引用而不是值来分配对象/数组。
这可以
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
这不可以
nestedNumbers = [[1], [2]];
numbersCopy = [];
for (i = 0; i < nestedNumbers.length; i++) {
numbersCopy[i] = nestedNumbers[i];
}
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
3.while 循环(浅拷贝)
同 for 循环一样,不纯的、命令式的, blah, blah, blah... 但有效!
numbers = [1, 2, 3];
numbersCopy = [];
i = -1;
while (++i < numbers.length) {
numbersCopy[i] = numbers[i];
}
注意:这也通过引用而不是按值分配对象/数组。
这可以
numbersCopy.push(4);
console.log(numbers, numbersCopy);
// [1, 2, 3] and [1, 2, 3, 4]
// numbers is left alone
这不可以
nestedNumbers = [[1], [2]];
numbersCopy = [];
i = -1;
while (++i < nestedNumbers.length) {
numbersCopy[i] = nestedNumbers[i];
}
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1, 300], [2]]
// [[1, 300], [2]]
// They've both been changed because they share references
4.Array.map (浅拷贝)
回到现代领域,我们将找到 map 函数,基于数学,map 是将一组转换为另一种类型的集合,同时保留结构的概念。
这意味着 Array.map 每次都返回一个长度相同的数组。
要使列表中数字加倍,可以使用 map 带加倍函数
numbers = [1, 2, 3];
double = (x) => x * 2;
numbers.map(double);
什么是克隆
没错,这篇文章是关于克隆数组的。要复制数组,只需返回 map 调用中的元素即可。
numbers = [1, 2, 3];
numbersCopy = numbers.map((x) => x);
如果你想更数学一点,(x)=> x 被称为身份。它返回给出的任何参数。
map(identity) 复制一个列表
identity = (x) => x;
numbers.map(identity);
// [1, 2, 3]
注意:这也通过引用而不是按值分配对象/数组。
5.Array.filter (浅拷贝)
此函数返回一个数组,就像 map 一样,但它不能保证长度相同。
如果你要过滤偶数数字怎么办?
[1, 2, 3].filter((x) => x % 2 === 0)
// [2]
输入数组长度为3,但结果长度为1。
如果 filter 始终返回 true,就会重复
numbers = [1, 2, 3];
numbersCopy = numbers.filter(() => true);
每个元素都通过测试,因此返回。
注意:这也通过引用而不是按值分配对象/数组。
6.Array.reduce (浅拷贝)
使用 reduce 来克隆数组感觉非常不好,因为它远比此强大,让我们开始...
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);
reduce 在循环遍历列表时转换初始值。
这里的初始值是一个空数组,我们将逐步填充每个元素。必须从要在下一次迭代中使用的函数返回该数组。
注意:这也通过引用而不是按值分配对象/数组。
7.Array.slice (浅拷贝)
slice 根据你提供的开始/结束索引返回数组的副本。
如果我们想要前3个元素:
[1, 2, 3, 4, 5].slice(0, 3);
// [1, 2, 3]
// Starts at index 0, stops at index 3
如果我们想要所有元素,请不要给出任何参数
numbers = [1, 2, 3, 4, 5];
numbersCopy = numbers.slice();
// [1, 2, 3, 4, 5]
注意:这也通过引用而不是按值分配对象/数组。
8.JSON.parse 和 JSON.stringify (深拷贝)
JSON.stringify 将对象转换为字符串
JSON.parse 将字符串转换为对象
组合它们可以将对象转换为字符串,然后反转该过程以创建全新的数据结构。
注意:这也通过引用而不是按值分配对象/数组。
nestedNumbers = [[1], [2]];
numbersCopy = JSON.parse(
JSON.stringify(nestedNumbers)
);
numbersCopy[0].push(300);
console.log(nestedNumbers, numbersCopy);
// [[1], [2]]
// [[1, 300], [2]]
// These two arrays are completely separate!
9.Array.concat (浅拷贝)
concat 将数组与值或其他数组组合在一起。
[1, 2, 3].concat(4); // [1, 2, 3, 4]
[1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5]
如果你不提供任何内容或空数组,则返回副本。
[1, 2, 3].concat(); // [1, 2, 3]
[1, 2, 3].concat([]); // [1, 2, 3]
注意:这也通过引用而不是按值分配对象/数组。
10.Array.from (浅拷贝)
这可以将任何可迭代对象转换为数组。给数组返回一个副本。
numbers = [1, 2, 3];
numbersCopy = Array.from(numbers)
// [1, 2, 3]
注意:这也通过引用而不是按值分配对象/数组。
总结
嗯,这很有趣
我试着只用一步就克隆了。如果你采用多种方法和技术,你会发现更多方法。