对象浅拷贝和深拷贝的拷贝方法
如果要拷贝的对象里面没有object或者array这种复杂的类型属性,那么就使用浅拷贝。如果想完整复制一个对象,对象里有object或者array这种复杂的类型属性,且想要复制的对象和原对象互不影响,就使用深拷贝。
浅拷贝:
JavaScript 中,数组有两个方法 concat 和 slice 是可以实现对原数组的拷贝的。同时,ES6 中 引入了 Object.assgn 方法和 ... 扩展运算符也能实现对对象的拷贝。
let arr1 = [1, 2, 3, 4, { name: 'Mary' }]; // 浅拷贝 const arr2 = arr1.concat(); const arr3 = arr1.slice(0); const arr4 = [...arr1]; // 操作 arr1.push(6); arr1[4].name = 'Jack'; console.log(arr1); // [ 1, 2, 3, 4, { name: 'Jack' }, 6 ] console.log(arr2); // [ 1, 2, 3, 4, { name: 'Jack' } ]
let obj1 = { a:1, b:'b', c:{ name: 'Mary' }};
// 浅拷贝
const obj2 = { ...obj1 };
const obj3 = Object.assign({}, obj1);
// 操作
obj1.a = 2;
obj1.b = 'newB';
obj1.c.name = 'June';
console.log(obj1); // { a: 2, b: 'newB', c: { name: 'June' } }
console.log(obj2); // { a: 1, b: 'b', c: { name: 'June' } }
深拷贝:
可以通过递归一层层拷贝。
function deepCopy(obj, appeard = new Map()) { if (!(obj instanceof Object)) return obj; // 如果是原始数据类型 if (appeard.has(obj)) return appeard.get(obj); // 如果已经出现过 const result = Array.isArray(obj) ? [] : {}; appeard.set(obj, result); // 将新对象放入map // 遍历所有属性进行递归拷贝 [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)] .forEach(key => { result[key] = deepCopy(obj[key], appeard); }); return result; }
或者通过JSON转化。JSON转化的优缺点:
优点:可以处理纯对象的深拷贝
缺点:
- 如果对象里有函数,函数无法被拷贝下来(RegExp/函数不会拷贝)
- 无法拷贝old对象原型链上的属性和方法
- 当数据的层次很深,会栈溢出
- undefined,NaN, -Infinity, Infinity 都会被转化成null
- new Date()会被转成字符串
const newObj = JSON.parse(JSON.stringify(old));
深拷贝的效果:
let obj1 = { a:1, b:'b', c:{ name: 'Mary' }};
const obj2 = deepCopy(obj1);
// 操作
obj1.c.name = 'Anna';
console.log(obj1); // { a: 1, b: 'b', c: { name: 'Anna' } }
console.log(obj2); // { a: 1, b: 'b', c: { name: 'Mary' } }

浙公网安备 33010602011771号