Skip to content

deepClone

深克隆

参数

参数名参数类型参数说明
targetany要克隆的对象
mapWeakMap<object, any>用来存对象做循环引用的判断

源代码&使用

ts
import { deepClone } from '@manzhixing/utilsxy';

const map = new Map();
map.set("name", "chengbotao");

const set = new Set();
set.add("utilsxy");
set.add("chengbotao");

const obj = {
  field: 1,
  fieldUn: undefined,
  fieldObj: {
    age: 28,
  },
  fieldArr: [2, 4, 8],
  empty: null,
  map,
  set,
  bool: new Boolean(true),
  num: new Number(2),
  str: new String(2),
  symbol: Object(Symbol(1)),
  date: new Date(),
  reg: /\d+/,
  error: new Error(),
  fun: () => {
    console.log("Hello Family!");
  },
  fun1: function (a, b) {
    return a + b;
  },
};

const copy = deepClone(obj);
ts
/*
 * @Author: Chengbotao
 * @Contact: https://github.com/chengbotao
 */

export function deepClone(target: any, map = new WeakMap()) {
  if (target === null || typeof target !== 'object') {
    return target;
  }

  if (map.get(target)) {
    return target;
  }

  const Ctor = target.constructor;
  const ctorName = Ctor.name;
  if (/^(RegExp|Date|Number|String|Boolean|Error)$/i.test(ctorName)) {
    return new Ctor(target);
  }

  if (ctorName === 'Symbol') {
    return Object(Object.prototype.valueOf.call(target));
  }

  if (ctorName === 'Map') {
    const cloneMap = new Map();
    map.set(target, true);
    target.forEach((value: unknown, key: unknown) => {
      cloneMap.set(deepClone(key, map), deepClone(value, map));
    });
    return cloneMap;
  }

  if (ctorName === 'Set') {
    const cloneSet = new Set();
    map.set(target, true);

    target.forEach((value: unknown) => {
      cloneSet.add(deepClone(value, map));
    });
    return cloneSet;
  }

  map.set(target, true);

  const cloneResult: Record<string, any> = Array.isArray(target) ? [] : {};

  Object.getOwnPropertyNames(target).forEach((key: string) => {
    cloneResult[key] = deepClone(target[key], map);
  });

  return cloneResult;
}