闽公网安备 35020302035485号
想必很多人对深拷贝的概念只停留在JSON.parse(JSON.stringify()),但他有个致命的缺陷,就是无法拷贝undefined、function等类型的值。
下面让我们浅浅的了解下深拷贝:深拷贝是一种拷贝对象的方式,它会创建一个完全独立于原始对象的新对象。深拷贝不仅复制了对象的引用,还复制了对象的所有内部属性和子对象。这意味着源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。

function deepCopy(val, hash = new WeakMap()) {
//堆代码 duidaima.com
}
这里定义了一个名为deepCopy的函数,它接受两个参数:val(要拷贝的值)和hash(一个WeakMap对象,用于存储已经拷贝过的对象和它们的拷贝,默认为一个新的WeakMap)。if (typeof val !== 'object' || val === null) {
return val;
}
首先,函数检查val的类型。如果val不是对象或者为null,则直接返回val本身,因为基本数据类型如(字符串、数字、布尔值等)是按值传递的,不需要深度拷贝。if (hash.has(val)) {
return hash.get(val);
}
接下来函数检查val是否已经在hash中存在。如果存在,说明之前已经拷贝过这个对象,直接返回拷贝的引用,避免无限递归。let copy;
if (Array.isArray(val)) {
copy = [];
} else if (val instanceof Date) {
copy = new Date(val.getTime());
} else if (val instanceof RegExp) {
let pattern = val.valueOf()
let flags = ''
flags += pattern.global ? 'g' : '';
flags += pattern.ignoreCase ? 'i' : '';
flags += pattern.multiline ? 'm' : '';
copy = new RegExp(pattern.source, flags);
} else if (typeof val === 'function') {
// 对于函数,我们直接返回引用(浅拷贝)
copy = val;
} else {
copy = {};
}
根据val的类型,函数创建不同的拷贝:如果val是普通对象,创建一个新的空对象copy。
hash.set(val, copy);在创建拷贝后,将原始对象val和它的拷贝copy存入hash中,以便后续处理可能出现的循环引用。
for (let key in val) {
if (val.hasOwnProperty(key)) {
copy[key] = deepCopy(val[key], hash);
}
}
使用for...in循环遍历val的所有可枚举属性,并对每个属性递归调用deepCopy函数,将结果赋值给copy的相应属性。// 使用示例
let val = {
a: 1,
b: {
c: 2,
d: [3, 4]
}
};
let copiedval = deepCopy(val);
console.log(copiedval); // { a: 1, b: { c: 2, d: [3, 4] } }
console.log(copiedval.b.d === val.b.d); // false,说明是深拷贝
没毛病!function deepCopy(val, hash = new WeakMap()) {
// 如果传入的不是对象或数组,直接返回
if (typeof val !== 'valect' || val === null) {
return val;
}
// 如果对象已经存在于哈希表中,直接返回引用
if (hash.has(val)) {
return hash.get(val);
}
// 创建一个新的拷贝
let copy;
if (Array.isArray(val)) {
copy = [];
} else if (val instanceof Date) {
copy = new Date(val.getTime());
} else if (val instanceof RegExp) {
let pattern = val.valueOf()
let flags = ''
flags += pattern.global ? 'g' : '';
flags += pattern.ignoreCase ? 'i' : '';
flags += pattern.multiline ? 'm' : '';
copy = new RegExp(pattern.source, flags);
} else if (typeof val === 'function') {
// 对于函数,我们直接返回引用(浅拷贝)
copy = val;
} else {
copy = {};
}
// 将新对象存入哈希表
hash.set(val, copy);
// 堆代码 duidaima.com
// 递归复制对象的属性
for (let key in val) {
if (val.hasOwnProperty(key)) {
copy[key] = deepCopy(val[key], hash);
}
}
return copy;
}
手撕深拷贝是面试经常遇到的问题,了解并掌握深拷贝,对自身开发也是有很大帮助!