← 返回文章列表
JavaScript·975 次阅读

structuredClone:原生深拷贝终于来了

structuredClone:原生深拷贝终于来了

深拷贝是 JS 的经典面试题,也是真实需求。之前写过一篇手写深拷贝的文章讲原理,这次聊聊 2022 年落地的原生方案 structuredClone,以及它能不能替代各种老办法。

老办法各自的问题

// 1. 展开运算符:只有一层
const copy = { ...obj } // obj.nested 还是引用

// 2. JSON 序列化:丢数据
JSON.parse(JSON.stringify({
  date: new Date(),      // 变成字符串
  reg: /abc/g,           // 变成 {}
  fn: () => {},          // 直接消失
  undef: undefined,      // 直接消失
  big: 10n,              // 抛 TypeError
  // 循环引用 -> 抛 TypeError: Converting circular structure
}))

JSON 方案胜在简单,但限制太多:类型丢失、undefined 消失、循环引用爆炸。lodash 的 cloneDeep 功能全,但为一个方法引整个库不划算。

structuredClone 上手

const original = {
  date: new Date(),
  set: new Set([1, 2]),
  map: new Map([['a', 1]]),
  nested: { arr: [1, 2, 3] },
}
original.self = original // 循环引用

const copy = structuredClone(original)
copy.nested.arr.push(4)
console.log(original.nested.arr) // [1, 2, 3] 不受影响
console.log(copy.date instanceof Date) // true,类型保留
console.log(copy.self === copy) // true,循环引用正确指向新对象

一行调用,类型保留,循环引用也正确处理。浏览器(2022 年起)和 Node 17+ 都有。

能力边界:不是所有东西都能拷

structuredClone 用的是结构化克隆算法(和 postMessage 传数据同一套),它拷贝的是"数据",不是"活的对象":

  • ❌ 函数:包括方法,直接抛 DataCloneError
  • ❌ DOM 节点:不能拷
  • ❌ 原型链和类实例:拷完变成普通对象,copy instanceof MyClass 是 false
  • ❌ 属性描述符、getter/setter:只拷值,不拷行为
  • ✅ Date、RegExp、Map、Set、ArrayBuffer、TypedArray、Blob、File、ImageData 等都支持

所以它的定位很清晰:纯数据的深拷贝。Vue/React 里 clone state、IndexedDB 存取、Web Worker 传参,都是它的主场。带方法的类实例、需要保留原型的对象,还是得想别的办法。

性能对比

小对象上 JSON 方案和 structuredClone 差别不大(都是微秒级)。大对象(几百 KB 的嵌套结构)实测 structuredClone 更快,而且不用先序列化成字符串再过一遍 parse,内存占用也更优。

// 简单 benchmark 一下(Node 环境)
const data = { /* 大对象 */ }
console.time('json')
JSON.parse(JSON.stringify(data))
console.timeEnd('json')

console.time('clone')
structuredClone(data)
console.timeEnd('clone')

小结

方案 嵌套 特殊类型 循环引用 类实例
展开运算符 ❌ 浅 保留引用 ❌ 原型保留(浅)
JSON 序列化 ✅ ❌ 丢 ❌ 抛错 ❌
structuredClone ✅ ✅ 大部分 ✅ ❌ 变普通对象
lodash.cloneDeep ✅ ✅ ✅ 保留

日常首选 structuredClone,遇到类实例再上 cloneDeep。原生能力的完善让"手写深拷贝"越来越像一道纯粹的面试题——理解原理依然有价值,但生产代码里交给平台就好。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4