浅拷贝
lodash.clone
var _ = require('lodash');
var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]};
var obj2 = _.clone(obj1);console.log(obj1.b.f === obj2.b.f);// true
...
运算符
Object.assign
Array.prototype.concat()
Array.prototype.slice()
深拷贝
JSON.parse(JSON.stringify())
缺点:只适用JSON安全的对象
- 循环引用无法拷贝,BigInt报错
- 丢失对象的constructor
- Infinity和-Infinity为null
- 只能序列化对象的可枚举属性
- 正则,函数,undefined
- Symbol、undefined,Function会丢失,
- 正则、Error,Map、Set变空对象
- NAN会变null
- 日期 Date 对象变字符串
const test = { name: "test"};
const data = { a: "123",
b: 123,
c: true,
d: [43, 2],
e: undefined,
f: null,
g: function() { console.log("g"); },
h: new Set([3, 2, null]),
i: Symbol("fsd"),
j: test,
k: new Map([ ["name", "张三"], ["title", "Author"] ]),
l: NaN,
m: new RegExp(".*?"),
n: new Date()
};
console.log(JSON.parse(JSON.stringify(data)))
lodash.cloneDeep
const _ = require('lodash');
const obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3]};
const obj2 = _.cloneDeep(obj1);console.log(obj1.b.f === obj2.b.f);
MessageChannel
- 如果需要拷贝的对象没有函数,可以使用MessageChannel实现
function deepClone(val) {
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel()
port2.onmessage = e => resolve(e.data)
port1.postMessage(val)
})
}
递归实现
- 首先实现一个最简单的深拷贝
function deepClone(target) {
let cloneTarget = {};
const keys=Object.keys(target)
for (const key of keys) {
cloneTarget[key] = target[key];
}
return cloneTarget;
};
- 如果是原始类型直接返回,引用类型,递归拷贝
function deepClone(target) {
if(typeof target==='object'){
let cloneTarget = Array.isArray(target) ? [] : {};
const keys = Object.keys(target)
for (const key of keys) {
cloneTarget[key] = deepClone(target[key]);
}
return cloneTarget;
}else {
return target
}
};
- 解决循环引用
function deepClone(target,map = new Map()) {
if(typeof target==='object'){
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.has(target)) {
return target;
}
map.set(target, cloneTarget);
const keys = Object.keys(target)
for (const key of keys) {
cloneTarget[key] = deepClone(target[key],map);
}
return cloneTarget;
}else {
return target
}
};
- 进一步完善
单独处理各个数据类型 funtion map set 等等
function deepClone(target, map = new WeakMap()) {
if (typeof target === 'object') {
if (target === null) {//null
return null
}
if(target instanceof Date){
return target
}
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.has(target)) {
return target;
}
map.set(target, cloneTarget);
const keys = Object.keys(target)
for (const key of keys) {
cloneTarget[key] = deepClone(target[key], map);
}
return cloneTarget;
} else {
return target
}
}
Proxy
//todo