【03】手动实现深拷贝

2021-02-24  本文已影响0人  李俊佚

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

可以发现,当我们使用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()
//}

拷贝成功。

上一篇下一篇

猜你喜欢

热点阅读