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;
    }

    很全的深度克隆函数。

    原文:地址

  • 相关阅读:
    maven打包
    Description Resource Path Location Type Project configuration is not up-to-d
    GoldenGate
    maven打包 把要的依赖也打进去 配置
    mysql如何优化where子句
    根据状态计算操作状态
    kafka direct模式
    Kafka Connect
    Kafka Streams
    如何看源码
  • 原文地址:https://www.cnblogs.com/tcxq/p/12306453.html
Copyright © 2011-2022 走看看