数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。JS 中的数组是可变的,这说明在创建数组之后还可以修改数组的内容。
这意味着要拷贝一个数组,咱们不能简单地将旧数组分配给一个新变量,它也是一个数组。如果这样做,它们将共享相同的引用,并且在更改一个变量之后,另一个变量也将受到更改的影响。这就是我们需要克隆这个数组的原因。
接着来看看一些关于拷贝何克隆数组的有趣方法和技巧。
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
这个做法是可行,但比较多余,少用
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]
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]
请注意,上面这些方法执行的是浅拷贝,就是数组是元素是对象的时候,咱们更改对象的值,另一个也会跟着变,就能技巧4来说,如果咱们的数组元素是对象,如下所示:
const authors = [
{ name: '前端小智', age: 25 },
{ name: '王大冶', age: 30 },
]
const copy = [...authors ]
copy[0].name = '被更改过的前端小智'
console.log(copy)
console.log(authors)
所以上面的技巧适合简单的数据结构,复杂的结构要使用深拷贝。数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。
原文:https://medium.com/
来源:twitter
译者:前端小智
javascript的深拷贝和浅拷贝主要是针对像Object, Array这样的复杂对象的,简单理解为浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。
JSON.parse(),JSON.stringify()实现对对象的深拷贝以及兼容性问题,根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系。
克隆JavaScript对象,首页想到的是obj = eval(uneval(obj)),但这是非标准的,推荐使用jquery提供的jQuery.extend方法,因为它包含了一些额外的类型验证逻辑,并且不会复制未定义的属性等。
在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?对象的深拷贝与浅拷贝的区别如下:浅拷贝:仅仅复制对象的引用,而不是对象本身;深拷贝:把复制的对象所引用的全部对象都复制一遍。
可以看出来,改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;同样:改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;
记录一个做leetcode看答案学到的小知识。。。浅拷贝实现一些特殊的功能的一些应用场景,比如:我们有一个需求如下
我们常常会用到拷贝对象的功能,而拷贝有浅拷贝和深拷贝2种。这篇文章会着重讲2个方面:1: 浅拷贝和深拷贝的区别2: 浅拷贝和深拷贝的具体实现,拷贝我们常常用在把A对象的属性copy到B对象,这样B对象就拥有了A对象的属性。
了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题
JavaScript中有两种数据类型,基本数据类型如undefined、null、boolean、number、string,另一类是Object。简单数据类型只存储在内存中的栈区,复制的时候是值传递给新的索引。而复杂数据类型由栈区和堆区共同储存
数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。JS 中的数组是可变的,这说明在创建数组之后还可以修改数组的内容。这意味着要拷贝一个数组,咱们不能简单地将旧数组分配给一个新变量
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!