美文网首页
js实现深拷贝(deepClone)

js实现深拷贝(deepClone)

作者: 技术体验师_萦回 | 来源:发表于2023-12-14 18:42 被阅读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))
    

    相关文章

      网友评论

          本文标题:js实现深拷贝(deepClone)

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