浅拷贝 1.es3写法 1 2 3 4 5 6 let originObj = {};let cloneObj = {};for (const key in originObj) { cloneObj[key] = originObj[key]; }
2.es5写法 1 2 3 4 5 6 7 8 9 10 Object .getOwnPropertyNames (originObj).forEach (function (key ) { cloneObj[key] = originObj[key] }) Object .getOwnPropertyNames (originObj).forEach (function (key ) { const des = Object .getOwnPropertyDescriptor (originObj, key); Object .defineProperty (cloneObj, key, des); })
3.es6的写法 1 2 3 4 5 6 7 8 9 10 11 12 for (const key of Object .keys (originObj)) { cloneObj[key] = originObj[key]; } for (const [key, value] of Object .entries (originObj)) { cloneObj[key] = value; } Object .assign (cloneObj, originObj);
深拷贝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function deepClone (obj ) { if (typeof obj !== 'object' || obj == null ) { return obj; } if (obj instanceof Date ) return new Date (obj); if (obj instanceof RegExp ) return new RegExp (obj); let newObj = ({}).toString .call (obj) === '[object Array]' ? [] : {}; for (const key in obj) { if (Object .hasOwnProperty .call (obj, key)) { newObj[key] = deepClone (obj[key]) } } return newObj; }
WeakMap解决拷贝死循环 上述深拷贝方法有个缺陷,如下:
1 2 3 4 5 let obj1 = {};let obj2 = {};obj1.obj2 = obj2; obj2.obj1 = obj1; deepClone (obj2);
会循环引用,最后导致栈溢出。

WeakMap的key是弱引用类型,如果键名在外部没有被引用了,那么键名和键值会自动被内存回收掉。
WeakMap 就是为了解决这个问题而诞生的,它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function deepClone (obj, hashMap = new WeakMap () ) { if (typeof obj !== 'object' || obj == null ) { return obj; } const hashKey = hashMap.get (obj); if (hashKey) return hashKey; let newObj = new obj.constructor ( ); hashMap.set (obj, newObj) for (const key in obj) { if (Object .hasOwnProperty .call (obj, key)) { newObj[key] = deepClone (obj[key]) } } return newObj; }
1 2 3 4 5 let obj1 = {};let obj2 = {};obj1.obj2 = obj2; obj2.obj1 = obj1; deepClone (obj2);
