BUG-JS对象深拷贝

2019-02-01  本文已影响16人  _LG_

对象深拷贝这个问题折磨了笔者好几天,简直痛不欲生。最大的问题是笔者认为自己写的都没有问题。

1.png

场景:将一个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是相互独立的(之后会解释为什么这么想)。
从以上代码可以得出流程:

对象深拷贝.png

因此,需要重新构建一个数组,然后将该数组拷贝给bdoctor属性:

   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窗口,按照上面的步骤运行了一遍,如下:

测试.png
就是这样,才会如此地确定Object.assign({}, a)是深拷贝。确并没有认真思考对象属性的值的类型,一个是不可变类型,一个是可变类型,就这样认为它们是等同的。

小结, 产生这个bug的原因有两点 :

  1. 一方面知识点掌握地不够熟练
  2. 都已经定位到bug产生的地方了,但是还是理所当然地认为没有错,没有原汁原味模拟出项目中代码产生结果的每一步。
上一篇下一篇

猜你喜欢

热点阅读