手动实现扁平化数组、深拷贝

以下是手写数组扁平化和深拷贝的实现方案:


一、手写数组扁平化(支持深度控制)

// 方法一:递归实现(默认无限深度)
function flattenDeep(arr) {
  return arr.reduce((acc, item) => {
    return acc.concat(Array.isArray(item) ? flattenDeep(item) : item);
  }, []);
}

// 方法二:循环实现(可指定深度 flatten(arr, 2) )
function flatten(arr, depth = Infinity) {
  while (arr.some(item => Array.isArray(item)) && depth > 0) {
    arr = [].concat(...arr);
    depth--;
  }
  return arr;
}

示例测试:

const nestedArr = [1, [2, [3, [4]]]];

flattenDeep(nestedArr); // [1,2,3,4]
flatten(nestedArr, 2);  // [1,2,3,[4]]

二、手写深拷贝(支持循环引用和常见类型)

function deepClone(source, hash = new WeakMap()) {
  // 处理非对象或 null
  if (typeof source !== 'object' || source === null) return source;

  // 循环引用直接返回
  if (hash.has(source)) return hash.get(source);

  // 处理特殊对象类型
  if (source instanceof Date) return new Date(source);
  if (source instanceof RegExp) return new RegExp(source);

  // 初始化克隆对象/数组
  const target = new source.constructor();
  hash.set(source, target);

  // Symbol 类型单独处理
  const symKeys = Object.getOwnPropertySymbols(source);
  if (symKeys.length) {
    symKeys.forEach(symKey => {
      target[symKey] = deepClone(source[symKey], hash);
    });
  }

  // 遍历普通属性
  for (const key in source) {
    if (source.hasOwnProperty(key)) {
      target[key] = deepClone(source[key], hash);
    }
  }
  return target;
}

示例测试:

const obj = {
  a: 1,
  b: [2, { c: 3 }],
  d: new Date(),
  e: /regexp/gi,
  f: Symbol('key'),
};
obj.self = obj; // 循环引用

const cloned = deepClone(obj);
console.log(cloned.d instanceof Date);  // true
console.log(cloned === obj);           // false

⚠️ 注意事项

  1. 深拷贝局限性
    • 未处理 Map/Set 等类型(需扩展)
    • 无法克隆函数(通常保留引用)
  2. 性能优化
    • WeakMap 处理循环引用比普通对象更优
  3. 数据类型覆盖
    • 基础版本已覆盖一般场景(对象/数组/日期/正则)

补充:解决 Map/Set 类型(扩展版本)

// 在 deepClone 中增加以下处理:
if (source instanceof Map) {
  target = new Map();
  source.forEach((value, key) => {
    target.set(deepClone(key, hash), deepClone(value, hash));
  });
}
if (source instanceof Set) {
  target = new Set();
  source.forEach(value => {
    target.add(deepClone(value, hash));
  });
}

如果还需要处理更多类型(如 Buffer、Promise 等),建议使用现成库如 lodash 的 _.cloneDeep

posted @   木燃不歇  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示