js实现深拷贝(deepClone)

2023-12-14  本文已影响0人  技术体验师_萦回

首先我们要实现一个getType函数对元素进行类型判断,直接调用Object.prototype.toString 方法。

      function getType(obj) {
        let map = {
          "[object Boolean]": "boolean",
          "[object Number]": "number",
          "[object String]": "string",
          "[object Function]": "function",
          "[object Array]": "array",
          "[object Date]": "date",
          "[object RegExp]": "regExp",
          "[object Undefined]": "undefined",
          "[object Null]": "null",
          "[object Object]": "object",
        };
        if (obj instanceof Element) {
          return "element";
        }
        return map[Object.prototype.toString.call(obj)];
      }

继续

deepClone递归实现

      function deepClone(target) {
        const type = getType(target);
        if (type == "array" || type == "object") {
          let _clone;
          // 复杂数据类型 递归实现
          if (type == "array") {
            _clone = [];
            target.forEach((element) => {
              _clone.push(deepClone(element));
            });
          } else {
            _clone = {};
            for (const key in target) {
              if (Object.hasOwnProperty.call(target, key)) {
                const element = target[key];
                _clone[key] = deepClone(element);
              }
            }
          }
          return _clone;
        } else {
          // 基础数据类型 直接返回
          return target;
        }
      }

对于function类型,这里是直接赋值的,还是共享一个内存值。这是因为函数更多的是完成某些功能,有个输入值和返回值,而且对于上层业务而言更多的是完成业务功能,并不需要真正将函数深拷贝。

处理循环引用

      function deepClone(target,stack) {
        const type = getType(target);
        if (type == "array" || type == "object") {
          let _clone;
          if(type == "array")  _clone = [];
          if(type == "object") _clone = {};
          // 检查循环引用并返回其对应的克隆
          stack || (stack = new WeakMap());
          var stacked = stack.get(target);
          if (stacked) {
            return stacked;
          }
          stack.set(target, _clone);
          // 复杂数据类型 递归实现
          if (type == "array") {
            target.forEach((element) => {
              _clone.push(deepClone(element, stack));
            });
          } else {
            for (const key in target) {
              if (Object.hasOwnProperty.call(target, key)) {
                const element = target[key];
                _clone[key] = deepClone(element, stack);
              }
            }
          }
          return _clone;
        } else {
          // 基础数据类型 直接返回
          return target;
        }
      }

测试用例如下

      // 测试用例3 循环引用 
      var objA = {
        name:'a'
      };
      var objB = {
        name:'b'
      };
      objA.prop = objB;
      objB.prop = objA;

      console.log(deepClone(objA))
上一篇下一篇

猜你喜欢

热点阅读