手记

JS深拷贝不要太简单

对象深拷贝

用递归实现深拷贝,这里的函数做了bind的处理,使其返回一个新的函数,至于值是对象的话会进行递归遍历,最后实现对象的深拷贝。

deepClone = (initalObj) => {
    const obj = {};
    if(typeof initalObj !== 'object'){
      return initalObj
    }
    for (const key in initalObj) {
      if (typeof initalObj[key] === 'object') {
        //对数组特殊处理
        if (Array.isArray(initalObj[key])) {
          //用map方法返回新数组,将数组中的元素递归
          obj[key] = initalObj[key].map(item => this.deepClone(item))
        } else {
          //递归返回新的对象
          obj[key] = this.deepClone(initalObj[key]);
        }
      } else if (typeof initalObj[key] === 'function') {
        //返回新函数
        obj[key] = initalObj[key].bind(obj);
      } else {
        //基本类型直接返回
        obj[key] = initalObj[key];
      }
    }
    return obj;
  }

const obj = {
  a: 1,
  b: {},
  c: { d: {}, g: () => {} },
  e: () =>{},
  f: function () {}
}
const newObj = deepClone(obj);
newObj.a === obj.a  //true
newObj.b === obj.b  //false
newObj.c === obj .false  //false
newObj.c.d === obj.c.d  //false
newObj.c.g === obj.c.g  //false
newObj.e === obj.e  //false
newObj.f === obj.f  //false

为什么需要深拷贝

理解一下引用类型

实际上JavaScript的对象是一个引用类型,那么可以这么理解const obj = {}这个表达式,实际上可以把obj理解成内存中的指针,指向该对象的一个内存地址。我们知道当我们进行如下操作时

const newObj = obj

实际上我们只是把内存的指针附给了newObj,好比我们把一栋房子的钥匙交给别人,而房子只有一栋的意思。所以理解这一点以后,我们就可以想象到,拷贝一个对象并不是那么简单的一件事

深拷贝做了什么

理解了引用类型以后,我们就可以想到。我们的对象里面也可以嵌套引用类型

const obj = {
  a: 1,
  b: {},
  c: { d: {}, g: () => {} },
  e: () =>{},
  f: function () {}
}

那么实际上深拷贝需要做的事情就是,把对象中的引用类型全部复制一遍。复制一个引用类型,就需要在内存中新开一个空间,然后在把原对象有的东西都塞进去。那么这样的意思就是,换了内存地址和内存,但是内容还是那些内容。这里的话需要一张图来解答

我们想做到的深拷贝是这样的

而不是这样的

实际上这也叫浅拷贝,关于浅拷贝的方式有很多种,接下来会分享一些。那么关于深拷贝的做了什么相信大家也能直观的看见了。

对象浅拷贝

// 方法一:
const newObj = {...obj}

//方法二:
const newObj = Object.assgin({},obj)

//方法三:
const newObj = Object.creact({},obj)

emm,简单记住第一种方法就行,也是最简单的一种。

后话

其实深拷贝也有很多种,但是无非就是换一个方式去拷贝每一份对象而已。主要是掌握拷贝时候的思路,如果需要别的类型,比如需要保留对象的prototype,那么我们在拷贝每一份对象的使用Object.create就可以。当然,如果有什么奇思妙想,也都可以添加,毕竟每个人的代码都有自己的思想

成功不在一朝一夕,我们都需要努力

1人推荐
随时随地看视频
慕课网APP

热门评论

实际场景中,方法应该不需要进行深拷贝吧,公用也是貌似不存在什么问题,这边还是为了演示深拷贝做的特殊处理吧

1、数组的处理中,map要不要加return? 2、为什么要加函数处理,感觉多此一举?

能否不用递归的方式进行深拷贝


查看全部评论