浅拷贝
lodash.clone
jsvar _ = 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 对象变字符串
jsconst 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
jsconst _ = 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实现
jsfunction deepClone(val) { return new Promise(resolve => { const { port1, port2 } = new MessageChannel() port2.onmessage = e => resolve(e.data) port1.postMessage(val) }) }
递归实现
- 首先实现一个最简单的深拷贝
jsfunction deepClone(target) { let cloneTarget = {}; const keys=Object.keys(target) for (const key of keys) { cloneTarget[key] = target[key]; } return cloneTarget; };
- 如果是原始类型直接返回,引用类型,递归拷贝
javascriptfunction 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 } };
- 解决循环引用
javascriptfunction 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 等等
jsfunction 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