现象:数组通过=赋值后,修改新数组会改变原数组。
解决方案:
1、用es6的扩展方法【...】,Object.assign() 仅限有一级数据的简单数据结构
2、先把数据JSON.stringify(),再JSON.parse()解析,此方法有局限,某些值拷贝后会发现变化
3、通用的复杂数据结构的深拷贝,参考:面试题之如何实现一个深拷贝 | 木易杨前端进阶
原理:
1、js中存储对象时的存储方式是用指针指向内存地址,用=赋值只是将指针赋给了新数据,实际指向的内存地址并没有变化。浅拷贝只是拷贝指针,深拷贝才是将指针连同内存一起拷贝。
2、(...)取出所有可遍历属性,拷贝到当前数组或对象中。
let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }
实际上等价于Object.assign
let bar = { a: 1, b: 2 };
let baz = Object.assign({}, bar); // { a: 1, b: 2 }
// 深拷贝方法1:
const obj = {
a: {
a1: 1,
a2: { a22: 3 }
},
b: { b1: 4 },
c: {
c1: {
c11: 12,
c12: 13,
c13: 14,
c14: { c114: 9 }
}
}
};
this.clone(obj);
clone(source: any): any {
const target: any = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
if (typeof source[i] === 'object') {
target[i] = this.clone(source[i]); // 注意这里
} else {
target[i] = source[i];
}
}
}
return target;
}
// 深拷贝方法2:
let obj2 = {
a: [1, 2, 3],
b: {
c: 2,
d: 3
}
}
this.deepClone(obj2);
deepClone(obj) {
function isObject(o) {
return (typeof o === 'object' || typeof o === 'function') && o !== null
}
if (!isObject(obj)) {
throw new Error('非对象')
}
let isArray = Array.isArray(obj)
let newObj = isArray ? [...obj] : { ...obj }
Reflect.ownKeys(newObj).forEach(key => {
newObj[key] = isObject(obj[key]) ? this.deepClone(obj[key]) : obj[key]
})
return newObj;
}