贝利信息

如何用javascript实现深拷贝与浅拷贝【教程】

日期:2026-01-26 00:00 / 作者:紅蓮之龍
JavaScript无万能深拷贝函数;JSON.parse(JSON.stringify())会丢失函数、undefined等且不支持循环引用;浅拷贝如{...obj}仅复制第一层,引用类型仍共享内存;手写深拷贝需递归+WeakMap防循环;生产环境推荐lodash.cloneDeep或structuredClone。

JavaScript 里没有“一键深拷贝”的万能函数,JSON.parse(JSON.stringify(obj)) 看似简单,但会丢函数、undefined、Symbol、循环引用、Date、RegExp 等;而浅拷贝用 Object.assign() 或展开运算符 {...obj} 就行,但只管第一层。

浅拷贝:只复制对象第一层属性值

浅拷贝本质是让新对象和原对象的顶层属性指向相同的内存地址(对引用类型而言)。常见写法有:

典型陷阱:const a = { x: 1, y: { z: 2 } }; const b = { ...a }; b.y.z = 99; console.log(a.y.z); // 输出 99 —— 因为 y 是引用,没被真正复制。

深拷贝:递归复制所有层级的可遍历属性

手写深拷贝需判断类型、避开循环引用、处理特殊对象。一个最小可用版本如下:

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj);
  
  const cloned = Array.isArray(obj) ? [] : {};
  hash.set(obj, cloned);
  
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      cloned[key] = deepClone(obj[key], hash);
    }
  }
  return cloned;
}

关键点:

为什么不用 JSON.parse(JSON.stringify(obj))

它看似简洁,但实际限制极多:

仅适合临时处理“干净”的纯数据对象(比如 API 返回的扁平 JSON 数据)。

现代项目中更推荐的方案

生产环境别自己造轮子,优先用成熟库:

注意:structuredClone 在 Node.j

s 17.0+ 才可用,且不支持 Error 对象和某些自定义类实例 —— 这些边界情况,往往才是深拷贝真正难搞的地方。