{"size": 657, "ext": "js", "max_stars_repo_path": "clone-deep.js", "max_stars_repo_name": "felixyoungzZ/hand-coded", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "clone-deep.js", "max_issues_repo_name": "felixyoungzZ/hand-coded", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "clone-deep.js", "max_forks_repo_name": "felixyoungzZ/hand-coded", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 18.25, "max_line_length": 84, "alphanum_fraction": 0.5585996956}
function isObject(obj) {
  return ['object', 'function'].some((type) => typeof obj === type) && obj !== null;
}

/**
 * 简易版深拷贝
 * TODO: 解决递归爆栈
 * 
 * @param {} obj 
 */
function deepClone(obj, hash = new WeakMap()) {
  // 值类型直接返回
  if (!isObject(obj)) {
    return obj;
  }

  if (typeof obj === 'function') {
    return obj;
  }

  // 用 hash 记录，解决循环引用
  if (hash.has(obj)) {
    return hash.get(obj);
  }

  // 结构做一层浅拷贝
  let newObj = Array.isArray(obj) ? [...obj] : { ...obj };
  hash.set(obj, newObj);

  // 递归调用
  Reflect.ownKeys(newObj).forEach((key) => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key];
  });

  return newObj;
}