深拷贝和浅拷贝是针对引用类型(对象类型跟数组类型)而言的。其中,浅拷贝,会创建一个新的对象,对原对象的属性进行拷贝,如果原对象中的属性值是基本数据类型,则直接拷贝属性值;如果属性值是引用类型,拷贝的则是指向这个属性值的地址。而深拷贝则是把原对象完整地拷贝一份出来,放到新的内存中。 总而言之,对于浅拷贝,如果属性值是引用类型,则新旧对象都可以对其进行修改。对于深拷贝而言,新旧对象则是独立的,互不影响。
实现过程
浅拷贝
// 判断值是否是对象类型
function isObject (val) {
if (val === null) {
return false;
}
const type = typeof val;
return type === 'object' || type === 'function';
}
function shallowCopy(origin) {
// 不是引用类型,直接返回值
if (!isObject(origin)) return origin;
const temp = Array.isArray(origin) ? [] : {};
// 浅拷贝,getOwnPropertySymbols是获取对象中Symbol类型的key
const keys = [...Object.keys(origin), ...Object.getOwnPropertySymbols(origin)];
keys.forEach(key => {
temp[key] = origin[key];
})
return temp
}
深拷贝
function deepCopy(origin) {
const visited = new WeakMap();
function base(target) {
if (!isObject(target)) return target;
// 处理循环引用,如: let a={}, b = {}; a.b=b; b.a=a; a引用b,b引用a
if (visited.get(target)) {
// target对象如果已经被访问过,直接返回值
return visited.get(target)
}
const result = Array.isArray(target) ? [] : {};
// 标识target对象已经被访问过了
visited.set(target, result)
const keys = [...Object.keys(target), ...Object.getOwnPropertySymbols(target)];
keys.forEach(key => {
const val = target[key];
if (isObject(val)) {
result[key] = base(val);
} else {
result[key] = val;
}
})
return result;
}
return base(origin)
}
测试
const test = {name: 'test', other: {age: '18'}};
const r1 = shallowCopy(test);
const r2 = deepCopy(test);