js实现一个通用的深拷贝

作者: bb7bb | 来源:发表于2018-12-01 17:48 被阅读2次

    对象深拷贝

    用递归实现深拷贝,这里的函数做了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 () {}
    }
    

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


    对象内存分配1

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


    深拷贝后对象内存分配2
    而不是这样的
    浅拷贝

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

    对象浅拷贝

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

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

    后话

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

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

    相关文章

      网友评论

        本文标题:js实现一个通用的深拷贝

        本文链接:https://www.haomeiwen.com/subject/wfzlcqtx.html