手写深拷贝时需特殊处理date和regexp:date用gettime()获取时间戳再new date()重建,regexp用source和flags属性构造新实例,二者须在递归中优先拦截,避免误入普通对象遍历分支。

手写深拷贝时,Date 和 RegExp 是两类需要特殊处理的内置对象:它们不能通过 new obj.constructor() 简单重建,因为构造函数行为与原始实例不一致(比如 RegExp 的 flags 会丢失、Date 的毫秒数可能被误解析)。
正确识别并单独处理 Date 对象
Date 实例需提取其时间戳(getTime() 或 valueOf()),再用该数值创建新 Date 实例。不能直接调用 new Date(obj),否则对非标准字符串输入可能出错;更稳妥的是只对已确认为 Date 的对象走时间戳路径。
- 用
obj instanceof Date或Object.prototype.toString.call(obj) === '[object Date]'判断 - 若为有效 Date(
!isNaN(obj.getTime())),返回new Date(obj.getTime()) - 避免使用
new Date(obj.toString()),防止时区或格式解析偏差
准确复制 RegExp 对象的 pattern 和 flags
RegExp 实例的 source(正则表达式字符串)和 flags(如 'gim')必须显式提取并传入新构造函数。直接 new RegExp(obj) 会丢失 flags,且对已有 RegExp 实例可能触发重复编译异常。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 用
obj instanceof RegExp或toString().slice(0, 8) === '/^(?:[^/]|\/)*$/'类方式判断(推荐前者) - 安全构造:
new RegExp(obj.source, obj.flags)—— 注意 IE 不支持obj.flags,可改用obj.toString().match(//([a-z]*)$/i)[1] || '' - 若需兼容老环境,可先用
obj.toString()解析完整正则字面量,再手动提取
整合进深拷贝主逻辑的注意事项
在递归深拷贝函数中,Date 和 RegExp 应在基础类型和普通对象之间提前拦截,避免落入 Object.keys() 遍历分支。它们属于“不可迭代但有特殊构造逻辑”的原生对象,优先级高于数组、普通对象,但低于 null/undefined/基本类型。
- 判断顺序建议:null/undefined → 基本类型 → Date → RegExp → Array → Object → 其他(如 Map/Set 可选扩展)
- 不要尝试对它们调用
JSON.parse(JSON.stringify()),Date 会变字符串,RegExp 会变空对象 - 若拷贝目标含循环引用,Date 和 RegExp 本身不构成循环,但需确保外层递归缓存机制不因它们跳过而漏处理
不复杂但容易忽略:Date 和 RegExp 的深拷贝不是“照着 constructor 调一下”,而是抓住其核心可序列化属性(时间戳、正则源码+标志),再用标准 API 重建。抓住这一点,就能避开大多数隐性 bug。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










