structuredClone()是首选方案,能正确克隆Date、RegExp等内置对象;手写需用Object.prototype.toString.call()精准判型,并用对应构造函数重建实例。

直接用 JSON.stringify() + JSON.parse() 行不通——Date 会变成字符串,RegExp 变成空对象 {},类型信息全丢。要正确复制 Date 和 RegExp,得明确它们的构造逻辑,并在深拷贝过程中单独处理。
用 structuredClone() 最省心(推荐首选)
现代浏览器(Chrome 98+、Firefox 94+、Safari 15.4+)已原生支持 structuredClone(),它能自动识别并正确克隆 Date、RegExp、Map、Set、ArrayBuffer 等,还支持循环引用:
-
structuredClone(new Date('2026-10-12'))→ 返回一个新 Date 实例,值相同但独立 -
structuredClone(/abc/gi)→ 返回一个新 RegExp 实例,.source和.flags都保留 - 不支持函数、Error、Promise、DOM 节点等,但对 Date/RegExp 这类内置对象覆盖完整
手写递归时必须单独判断和重建
如果需兼容旧环境或定制行为,手写深拷贝必须避开 typeof 的模糊性,改用 Object.prototype.toString.call() 精准识别类型,并用对应构造函数新建实例:
- 遇到
Date:直接new Date(date.getTime())或new Date(date.toString()) - 遇到
RegExp:用new RegExp(reg.source, reg.flags)(注意不能直接传reg,否则可能丢失 lastIndex) - 其他如 Map、Set 也要分别用
new Map([...map])、new Set([...set])并递归拷贝内部项
别踩这些坑
很多“看似能用”的方法其实悄悄改了语义:
-
new Date(obj)对非 Date 输入可能返回 Invalid Date,建议先判类型再处理 - RegExp 的
lastIndex属于运行时状态,structuredClone()不保留它,手写时通常也不复制——除非业务真依赖这个属性 - 不要用
obj.constructor来新建实例,因为子类或被篡改的 constructor 不可靠;优先用已知类型对应的构造器(如Date、RegExp)
不复杂但容易忽略。关键就两点:类型识别要准,重建方式要对。


















