const arr = [1, 2, 3, 4, 5];
const clone = JSON.parse(JSON.stringify(arr));
console.info(clone);
使用JSON.parse(JSON.stringify(arr))
的方式进行深拷贝时,并不会拷贝函数。
JSON.stringify()
方法会忽略JavaScript对象中的函数成员,并将其转换为空值。
因此,在使用JSON.parse(JSON.stringify(arr))
时,任何函数成员都将丢失并转换为undefined
。
使用 JSON.parse(JSON.stringify(arr))
进行深拷贝的方式相对简单且易于理解,适合用于处理普通的数据结构。
然而,它无法正确地处理一些特殊类型的数据,例如函数、正则表达式、日期对象等,因为这些类型在 JSON 格式中无法正确表示。
使用MessageChannel实现深拷贝。
MessageChannel除了用作通信还有一些hack的用法,比如用它来做deepClone。
function deepClone(target) {
return new Promise(resolve => {
const channel = new MessageChannel()
channel.port2.postMessage(target)
channel.port1.onmessage = eve => {
resolve(eve.data)
}
})
}
使用
const obj = {
name: '123',
b: {
c: 456
},
d: undefined
}
deepClone(obj).then(d => console.log(d))
这个方法比较优秀的地方在于undefined的不会丢失,循环引用的对象也不会报错,循环点会被置为undefined,不过不能复制函数。
使用 MessageChannel
实现异步深拷贝,可以正确地处理任何类型的数据,包括特殊类型。
由于它是异步的方式,所以性能可能会受到一定影响,特别是在处理大型数据结构时会更明显。
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
使用
const obj = { a: 1, b: { c: 2 }, d: [3, 4],getValue(){
return this.a;
}};
const clonedObj = deepClone(obj);
console.log(clonedObj);
这种方式会拷贝方法。
使用展开运算符可以轻松地复制
const arr = [1, 2, 3, 4, 5];
const clone = [...arr];
console.info(clone);
使用数组的slice方法复制数组
const arr = [1, 2, 3, 4, 5];
const clone = arr.slice();
console.info(clone);
slice()
是数组对象的一个方法,用于从数组中提取指定位置的元素创建一个新的数组。
slice()
方法不会修改原始数组,而是返回一个浅拷贝(shallow copy)的新数组。
slice()
方法可以接收两个参数,即 start
和 end
。起始位置 start
是要提取的起始索引(包含在提取范围内),结束位置 end
是要提取的结束索引(不包含在提取范围内)。
如果省略 end
参数,默认会提取到数组的末尾。