对象深拷贝这个问题折磨了笔者好几天,简直痛不欲生。最大的问题是笔者认为自己写的都没有问题。
场景:将一个a对象拷贝给b对象,改变a对象的属性的值,b对象不发生变化。然而问题出现了,b对象属性的值也跟着a对象发生变化了。
const a = {doctor: [{name: 'aa'}, {name: 'bb'}]};
const b = Object.assign({}, a);
a.doctor.push({name: 'cc'});
console.log(a); // {doctor: [{name: 'aa'}, {name: 'bb'}, {name: 'cc'}]}
console.log(b); // {doctor: [{name: 'aa'}, {name: 'bb'}, {name: 'cc'}]}
毫无疑问地,我认为Object.assign({}, a)
是一种深拷贝方法,将a对象拷贝给b,a和b是相互独立的(之后会解释为什么这么想)。
从以上代码可以得出流程:
因此,需要重新构建一个数组,然后将该数组拷贝给b
的doctor
属性:
const a = {doctor: [{name: 'aa'}, {name: 'bb'}]};
const b = {};
const c = a.doctor.map(data => {
return data;
});
b['doctor'] = c;
a.doctor.push({name: 'cc'});
console.log(a); // {doctor: [{name: 'aa'}, {name: 'bb'}, {name: 'cc'}]}
console.log(b); // {doctor: [{name: 'aa'}, {name: 'bb'}]}
so,这样做的话,就满足了一开始的要求。
现在来解释一波笔者为什么理所当然地认为Object.assign({}, a)
是深拷贝呢?因为一开始笔者在浏览器上的console窗口,按照上面的步骤运行了一遍,如下:
就是这样,才会如此地确定
Object.assign({}, a)
是深拷贝。确并没有认真思考对象属性的值的类型,一个是不可变类型,一个是可变类型,就这样认为它们是等同的。
小结, 产生这个bug的原因有两点 :
- 一方面知识点掌握地不够熟练
- 都已经定位到bug产生的地方了,但是还是理所当然地认为没有错,没有原汁原味模拟出项目中代码产生结果的每一步。
网友评论