| Array复制方法总结 | |||
|---|---|---|---|
| Array.slice(浅拷贝) | for() 、while | map、 filter | |
| Array.cancat | Array.reduce() | Object.assign() Es6 | |
| 扩展运算符 Es6 | Array.from()Es6 | JSON.parse(JSON.stringify()) | |
ES5 Array复制方法总结
1.Array.slice(浅拷贝)
slice 方法根据我们指定的start、end的index从原数组中返回一个浅拷贝的数组。
[1, 2, 3, 4, 5].slice(0, 3);
// [1, 2, 3]
// Starts at index 0, stops at index 3
// 当不给定参数时,就返回了原数组的拷贝

同样的,处理对象和数组的时候是引用而不是值复制
2. 遍历复制数组:for() 、while、map、 filter、 reduce
for()循环(浅拷贝) *
考虑到函数式编程变得越来越流行,我认为这种方法可能是最不受欢迎的。

let numbers = [1, 2, 3];
let numbersCopy = [];
for (let i = 0; i < numbers.length; i++) {
numbersCopy[i] = numbers[i];
}

这个方法不能有效的拷贝多维数组。
while()循环(浅拷贝)
numbers = [1, 2, 3];
numbersCopy = [];
i = -1;
while (++i < numbers.length) {
numbersCopy[i] = numbers[i];
}

Array.map(浅拷贝)
当我们使用map方法时,需要给出一个callback函数用于处理当前的数组,并返回一个新的数组元素。

同样的,处理对象和数组的时候是引用而不是值复制。
Array.filter(浅拷贝)
Array.filter方法同样会返回一个新数组,但是并不一定是返回同样长度的,这和我们的过滤条件有关。

同样的,处理对象和数组的时候是引用而不是值复制。
Array.reduce(浅拷贝)
其实用reduce来拷贝数组并没有展示出它的实际功能,但是我们还是要将其能够拷贝数组的能力说一下的
numbers = [1, 2, 3];
numbersCopy = numbers.reduce((newArray, element) => {
newArray.push(element);
return newArray;
}, []);

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数,将其结果汇总为单个返回值。
同样的,处理对象和数组的时候是引用而不是值复制。
3、Array.cancat(浅拷贝)

concat将数组与值或其他数组进行组合。
[1, 2, 3].concat(4); // [1, 2, 3, 4]
如果我们不指定参数或者提供一个空数组作为参数,就可以进行浅拷贝。

同样的,处理对象和数组的时候是引用而不是值复制。
ES6 方法总结
1. Object.assign() 浅拷贝
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

2. 扩展运算符(浅拷贝)

这个方法不能有效的拷贝多维数组。数组/对象值的拷贝是通过引用而不是值复制。
3、Array.from(浅拷贝)
可以将任何可迭代对象转换为数组。给一个数组返回一个浅拷贝。

同样的,处理对象和数组的时候是引用而不是值复制。
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]]
这个可以安全地拷贝深度嵌套的对象/数组
几种特殊情况
1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
var test = {
name: 'a',
date: [new Date(1536627600000), new Date(1540047600000)],
};
let = JSON.parse(JSON.stringify(test))

2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
const test = {
name: 'a',
date: new RegExp('\\w+'),
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'

3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
const test = {
name: 'a',
date: function hehe() {
console.log('fff')
},
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.error('ddd', test, copyed)

4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性,
例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
function Person(name) {
this.name = name;
}
const liai = new Person('liai');
const test = {
name: 'a',
date: liai,
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'

递归通用拷贝函数
递归拷贝函数(深拷贝:数组对象通用)
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (Array.isArray(obj)) {
return obj.reduce((arr, item, i) => {
arr[i] = deepCopy(item);
return arr;
}, []);
}
if (typeof obj === 'object') {
return Object.keys(obj).reduce((newObj, key) => {
newObj[key] = deepCopy(obj[key]);
return newObj;
}, {});
}
}
本文全面总结了ES5和ES6中数组复制的各种方法,包括浅拷贝和深拷贝技术,探讨了每种方法的适用场景及局限性,并提供了一个递归深拷贝函数。
317

被折叠的 条评论
为什么被折叠?



