美文网首页
【03】手动实现深拷贝

【03】手动实现深拷贝

作者: 李俊佚 | 来源:发表于2021-02-24 12:20 被阅读0次

    在上文中,已经提到了深浅拷贝的概念,以及常用的深浅拷贝的方法。这里进行一个简单的回顾:

    • 改变了一个变量的值,其他变量也一并改变的原因是引用类型数据,栈中存放的是地址,两个变量用了同一份堆中的数据。
    • 当数据为引用类型时,且想取消变量之间的关联,需要用到深浅拷贝。
    • 当数据仅有一层时,利用...扩展运算符能很简单的实现数据的拷贝。
    • 使用JSON.parse(JSON.stringify(obj));来进行深拷贝时,应注意对象中,不能存在Date、RegExp、Function类型的数据,不然会导致数据丢失。

    可以发现,当我们使用JSON.parse(JSON.stringify(obj));来进行深拷贝时,对象中不能存在Date、RegExp、Function类型的数据。但实际应用中,不可避免的会出现类似情况。此时应该怎么处理呢?

    这也是面试常问问题。

    1、使用Lodash JS工具库

    Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。其中封装了 array、number、objects、string 等等类型的数据处理方法。
    我们可以通过Lodash的cloneDeep(value)方法来实现对象的深拷贝。
    官网地址:https://www.lodashjs.com/docs/lodash.cloneDeep

    2、手写递归实现深拷贝

    我的实现思路如下:
    1、 通过递归实现深拷贝
    2、 通过typeof 操作符判断数据类型(typeof 不是函数,是一元操作符)
    3、 当数据类型为基本类型的时候和function,直接赋值
    4、 当数据类型为Object,且为数组和对象的时候,进行递归
    5、 利用for in 遍历数组和对象
    6、 利用hasOwnProperty判断是否需要拷贝原型上的属性
    7、 利用constructor判断数据类型。
    8、 利用constructor返回对创建此对象的数组函数的引用的特性,通过new 实现对Date、RegExp的深拷贝。

      function deepCopy(srouceData, onlyOwnProperty = true) {
        let resultData;
        if (typeof (srouceData) !== 'object') {
          return srouceData;
        } else {
          if (srouceData.constructor === Array || srouceData.constructor === Object) {
            resultData = new srouceData.constructor();
            for (let key in srouceData) {
              // 如果有需求,要过滤掉srouceData原型上的属性
              if (onlyOwnProperty) {
                if (Object.prototype.hasOwnProperty.call(srouceData, key)) {
                  resultData[key] = deep(srouceData[key])
                }
              } else {
                resultData[key] = deep(srouceData[key])
              }
            }
          } else {
            return new srouceData.constructor(srouceData);
          }
        }
        return resultData;
      }
    

    我们拿一个代码试试:

    let srouceObj = {
      a: 'a',
      b: { b1: 'b1', bt: new Date('2020-11-1') },
      c: [1, 2, 3],
      d: new Date(),
      e: new RegExp("[a-c]", "i"),
      f: function a() {
        alert('a')
      }
    }
    let copyObj = this.deepCopy(srouceObj);
    copyObj.b.b1 = 'b2';
    copyObj.d.setFullYear(2016);
    console.log(srouceObj)
    // {
    //  a: "a", 
    //  b: { b1: 'b1', bt: Sun Nov 01 2020 00:00:00 GMT+0800 (中国标准时间) }, 
    //  c: [1, 2, 3],
    //  d: Wed Feb 24 2021 12:13:53 GMT+0800 (中国标准时间), 
    //  e: /[a-c]/i,
    //  f: f a()
    //}
    console.log(copyObj)
    // {
    //  a: "a", 
    //  b: { b1: 'b2', bt: Sun Nov 01 2020 00:00:00 GMT+0800 (中国标准时间) }, 
    //  c: [1, 2, 3],
    //  d: Wed Feb 24 2016 12:13:53 GMT+0800 (中国标准时间), 
    //  e: /[a-c]/i,
    //  f: f a()
    //}
    

    拷贝成功。

    相关文章

      网友评论

          本文标题:【03】手动实现深拷贝

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