深浅拷贝
浅拷贝
浅拷贝是指,一个新的对象对原始对象的属性值进行精确地拷贝,如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值;如果拷贝的是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。
浅拷贝方法
- Object.assign
- 扩展运算符
- 数组操作(slice、concat)
实现
1 2 3 4 5 6 7 8 9 10
| function clone(params) { if (!params || typeof params !== 'object') return params;
const o = Array.isArray(params) ? [] : {}
for(let key in params) { o[key] = params[key] } return o; }
|
深拷贝
深拷贝是指,对于简单数据类型直接拷贝他的值,对于引用数据类型,在堆内存中开辟一块内存用于存放复制的对象,并把原有的对象类型数据拷贝过来,这两个对象相互独立,属于两个不同的内存地址,修改其中一个,另一个不会发生改变
JSON序列化的问题
- 拷贝的对象中如果有函数,undefined,symbol,当使用过JSON.stringify()进行处理之后,都会消失。
- 无法拷贝不可枚举的属性;
- 无法拷贝对象的原型链;
- 拷贝 Date 引用类型会变成字符串;
- 拷贝 RegExp 引用类型会变成空对象;
- 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
- 无法拷贝对象的循环应用,即对象成环 (obj[key] = obj)。
简单实现递归的深浅拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function deepClone(obj = {}, hash = new WeakMap()) { if (obj instanceof Date) { return new Date(obj) }
if (obj instanceof RegExp) { return new RegExp(obj) } if (hash.has(obj)) { return hash.get(obj) } const alldec = obj.getOwnPropertyDescriptors(obj)
const newObj = Object.create(obj, alldec);
hash.set(obj, newObj); for(const key of Object.keys(obj)) { if (obj[key] !== null && typeof obj[key] === 'object') { newObj[key] = deepClone(obj[key], hash) } else { newObj[key] = obj[key] } } return newObj }
|