# 深浅拷贝
# 浅拷贝
只是复制栈的内存地址,如果另一个对象改变堆的值,本身会发生改变
- 引用复制
function shallowCopy(target) {
const res = {};
for (let key in target) {
res[key] = target[key];
}
return res;
}
- Object.assign
var x = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var y = Object.assign({}, x);
console.log(y.b.f === x.b.f); // true
- 利用扩展运算符
# 深拷贝
完全拷贝,互不影响
- 递归实现
function deepclone(target = {}) {
if (target == null || typeof obj !== object) {
return target;
}
let res;
if (target instanceof Array) {
res = [];
} else {
res = {};
}
for (let key in target) {
// 保证不是原型对象上的属性
if (target.hasOwnPropetry(key)) {
res[key] = deepclone(target[key]);
}
}
return res;
}
完整版本
// Map 强引用,需要手动清除属性才能释放内存。
// WeakMap 弱引用,随时可能被垃圾回收,使内存及时释放,是解决循环引用的不二之选。
function cloneDeep(obj, map = new WeakMap()) {
if (!(obj instanceof Object)) return obj; // 基本数据
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
if (map.get(obj)) return map.get(obj); // 解决循环引用
if (obj instanceof Function) {
// 解决函数
return function() {
return obj.apply(this, [...arguments]);
};
}
const res = new obj.constructor(); // 下面是数组/普通对象/Set/Map 的处理
obj instanceof Object && map.set(obj, res);
if (obj instanceof Map) {
obj.forEach((item, index) => {
res.set(cloneDeep(index, map), cloneDeep(item, map));
});
}
if (obj instanceof Set) {
obj.forEach(item => {
res.add(cloneDeep(item, map));
});
}
Object.keys(obj).forEach(key => {
if (obj[key] instanceof Object) {
res[key] = cloneDeep(obj[key], map);
} else {
res[key] = obj[key];
}
});
return res;
}
const map = new Map();
map.set({ a: 1 }, "1");
const source = {
name: "Jack",
meta: {
age: 12,
birth: new Date("1997-10-10"),
ary: [1, 2, { a: 1 }],
say() {
console.log("Hello");
},
map
}
};
source.source = source;
const newObj = cloneDeep(source);
console.log(newObj.meta.ary[2] === source.meta.ary[2]); // false
console.log(newObj.meta.birth === source.meta.birth); // false
console.log(newObj);
- JSON.parse(JSON.stringify(target))
弊端
- obj 里有
date 对象
无法被序列化和反序列化,而是转为 date 字符串 - obj 里有
RegExp 对象
,Error 对象
序列化结果是空对象 - obj 里有
function
,undefined
会被丢失 - obj 里有
NaN
,Infinity
,-Infinity
序列化结果会变成 null
- loadash