详细代码: code demo
异同:
浅复制 (影子克隆): 只复制对象的基本类型, 对象类型, 仍属于原来的引用。
深复制 (深度克隆): 不紧复制对象的基本类, 同时也复制原对象中的对象。就是说完全是新对象产生的。
思路:
遍历所有该对象的属性,
如果该属性是 "object" 则需要特殊处理,
如果这个 object 对象比较特殊,是一个数组,那就创建一个新的数组并深复制数组里的元素
如果这个 object 对象是个非数组对象,那直接再对它递归调用深复制方法即可。
如果不是 "object",则直接正常复制就行。
对象的拷贝实现
浅拷贝
const obj = {
a:10,
b:{
c:'ccc'
}
};
// 方法一:Object.assign
const a={};
Object.assign(a,obj);
//方法二:对象解构
const a = {...obj,{}}深拷贝
function deepCopy(obj){
// object
if(typeof obj === 'object'){
// 排除null;
if(obj === null){
return null;
}
// array
if(Array.isArray(obj)){
const newArr = [];
for(let i=0;i<obj.length;i++){
const item = deepCopy(obj[i]);
newArr.push(item);
}
return newArr;
}
// other->object
const keys = Object.keys(obj);
const tempObj = {};
for(let key of keys){
const v = obj[key];
tempObj[key] = deepCopy(v);
}
return tempObj;
}else{
return obj;
}
};测试
const mock = ({
a:'111',
b:[1,2,3,4,5,{
s:null,
ss:undefined,
sss:[111]
}],
c:{
cc:{
ccc:'2222'
},
ccc02:[555],
}
});
// test
const r = deepCopy(mock);
r.b.s = 'new s value'; // r.b.s =>'new s value'; mock.b.s => null更完整的实现(支持 Map Set Symbol)
- 这一版实现修复了 Date、RegExp 的复制能力,上一版按照 object 直接复制会丢失他们的一些属性(不可枚举)
- 支持 Map、Set
- 支持 Symbol
function deepClone(target, map = new WeakMap()) {
// 1. 基本数据类型,直接返回
if (target === null || typeof target !== 'object') {
return target;
}
// 2. 日期对象
if (target instanceof Date) {
return new Date(target);
}
// 3. 正则对象
if (target instanceof RegExp) {
return new RegExp(target);
}
// 4. Map 处理
if (target instanceof Map) {
const cloneMap = new Map();
map.set(target, cloneMap); // 缓存,防止循环引用
target.forEach((value, key) => {
// 注意:Map 的 key 也可能是引用类型,所以 key 也需要深拷贝
cloneMap.set(deepClone(key, map), deepClone(value, map));
});
return cloneMap;
}
// 5. Set 处理
if (target instanceof Set) {
const cloneSet = new Set();
map.set(target, cloneSet); // 缓存
target.forEach(value => {
cloneSet.add(deepClone(value, map));
});
return cloneSet;
}
// 6. 处理循环引用
// 注意:因为上面已经处理了 Map/Set 并放入了 map,这里不会重复处理
if (map.has(target)) {
return map.get(target);
}
// 7. 初始化克隆对象 (数组或对象)
const cloneTarget = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target));
map.set(target, cloneTarget);
// 8. 遍历对象属性,递归拷贝
for (let key in target) {
if (target.hasOwnProperty(key)) {
cloneTarget[key] = deepClone(target[key], map);
}
}
// 9. 处理 Symbol 属性
const symbolKeys = Object.getOwnPropertySymbols(target);
for (let i = 0; i < symbolKeys.length; i++) {
const key = symbolKeys[i];
if (target.propertyIsEnumerable(key)) {
cloneTarget[key] = deepClone(target[key], map);
}
}
return cloneTarget;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。