zoukankan      html  css  js  c++  java
  • JS方法—完美的深度克隆

    const getType = obj => Object.prototype.toString.call(obj);
    
    const isObject = (target) => (typeof target === 'object' || typeof target === 'function') && target !== null;
    
    const canTraverse = {
      '[object Map]': true,
      '[object Set]': true,
      '[object Array]': true,
      '[object Object]': true,
      '[object Arguments]': true,
    };
    const mapTag = '[object Map]';
    const setTag = '[object Set]';
    const boolTag = '[object Boolean]';
    const numberTag = '[object Number]';
    const stringTag = '[object String]';
    const symbolTag = '[object Symbol]';
    const dateTag = '[object Date]';
    const errorTag = '[object Error]';
    const regexpTag = '[object RegExp]';
    const funcTag = '[object Function]';
    
    const handleRegExp = (target) => {
      const { source, flags } = target;
      return new target.constructor(source, flags);
    }
    
    const handleFunc = (func) => {
      // 箭头函数直接返回自身
      if(!func.prototype) return func;
      const bodyReg = /(?<={)(.|
    )+(?=})/m;
      const paramReg = /(?<=().+(?=)s+{)/;
      const funcString = func.toString();
      // 分别匹配 函数参数 和 函数体
      const param = paramReg.exec(funcString);
      const body = bodyReg.exec(funcString);
      if(!body) return null;
      if (param) {
        const paramArr = param[0].split(',');
        return new Function(...paramArr, body[0]);
      } else {
        return new Function(body[0]);
      }
    }
    
    const handleNotTraverse = (target, tag) => {
      const Ctor = target.constructor;
      switch(tag) {
        case boolTag:
          return new Object(Boolean.prototype.valueOf.call(target));
        case numberTag:
          return new Object(Number.prototype.valueOf.call(target));
        case stringTag:
          return new Object(String.prototype.valueOf.call(target));
        case symbolTag:
          return new Object(Symbol.prototype.valueOf.call(target));
        case errorTag: 
        case dateTag:
          return new Ctor(target);
        case regexpTag:
          return handleRegExp(target);
        case funcTag:
          return handleFunc(target);
        default:
          return new Ctor(target);
      }
    }
    
    const deepClone = (target, map = new WeakMap()) => {
      if(!isObject(target)) 
        return target;
      let type = getType(target);
      let cloneTarget;
      if(!canTraverse[type]) {
        // 处理不能遍历的对象
        return handleNotTraverse(target, type);
      }else {
        // 这波操作相当关键,可以保证对象的原型不丢失!
        let ctor = target.constructor;
        cloneTarget = new ctor();
      }
    
      if(map.get(target)) 
        return target;
      map.set(target, true);
    
      if(type === mapTag) {
        //处理Map
        target.forEach((item, key) => {
          cloneTarget.set(deepClone(key, map), deepClone(item, map));
        })
      }
      
      if(type === setTag) {
        //处理Set
        target.forEach(item => {
          cloneTarget.add(deepClone(item, map));
        })
      }
    
      // 处理数组和对象
      for (let prop in target) {
        if (target.hasOwnProperty(prop)) {
            cloneTarget[prop] = deepClone(target[prop], map);
        }
      }
      return cloneTarget;
    }

    很全的深度克隆函数。

    原文:地址

  • 相关阅读:
    模板代码生成器 Template Code Creater
    Oracle编程入门经典 第2章 SQLPlus和基本查询
    Oracle编程入门经典 第5章 体系结构
    数据仓库
    C++ WINDOWS API 第1章 Windows 应用程序开发入门
    C++ WINDOWS API 第2章 Windows API概要
    Oracle编程入门经典 第7章 表
    单交换机VLAN虚拟局域网划分
    Oracle日志文件被误删除
    Oracle编程入门经典 第4章 新9i示例模式
  • 原文地址:https://www.cnblogs.com/tcxq/p/12306453.html
Copyright © 2011-2022 走看看