javascript深拷贝默认不保留constructor,需通过object.create()复制原型并递归拷贝属性;structuredclone可保持内置类型constructor语义等价,但对自定义类有作用域要求;推荐用object.setprototypeof或object.create而非__proto__。

JavaScript 中的深拷贝默认不会保留原始对象的 constructor,因为大多数通用深拷贝方法(如 JSON.parse(JSON.stringify())、Lodash 的 cloneDeep)只复制可枚举属性和嵌套结构,不处理原型链和构造函数信息。要保留 constructor 指向,关键在于**同时复制原型(prototype)并正确设置新对象的 __proto__ 或使用 Object.setPrototypeOf()**。
手动实现:递归 + 原型继承
适用于自定义类实例或需要精确控制的场景。核心思路是:判断原对象是否有自定义 constructor(非 Object/Array 等内置类型),然后用 Object.create() 创建具有相同原型的新对象,再递归拷贝自有属性。
- 用
obj.constructor !== Object初步判断是否为自定义构造函数实例 - 用
Object.getPrototypeOf(obj)获取原型,再用Object.create(proto)创建新对象 - 对每个自有属性(
Object.keys()或Object.getOwnPropertyNames())递归深拷贝 - 对 getter/setter 属性,需用
Object.getOwnPropertyDescriptor()和Object.defineProperty()复制
使用 structuredClone(现代浏览器 & Node.js 18.7+)
structuredClone() 是原生支持深拷贝的方法,它会保留大部分对象特性,但不保留 constructor 引用本身——它只保证拷贝后对象的 constructor 指向与原对象“语义等价”的构造函数(例如 Date 实例拷贝后仍是 Date 实例)。对于自定义类,只要类在作用域中且可被识别(如非闭包内定义、未被 tree-shaken),它通常能维持正确的 constructor。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 支持 Map、Set、Date、RegExp、ArrayBuffer 等内置类型,且保持类型
- 对自定义类实例,要求其属性可序列化;否则抛错(如含 function、undefined、循环引用)
- 不复制原型上的方法或不可枚举属性,仅拷贝可枚举 + 可序列化数据
借助 class-aware 库(如 clone-deep + 自定义 handler)
像 clone-deep 或 lodash.cloneDeepWith 允许传入定制化克隆逻辑。你可以针对特定构造函数类型返回带正确原型的新实例。
- 例如:检测到
obj instanceof MyClass,就返回new MyClass(...)并手动赋值属性 - 注意避免调用可能有副作用的 constructor(如发请求、修改状态)
- 需手动处理继承链、Symbol 属性、不可枚举属性等边界情况
不推荐:直接改 __proto__(兼容性 & 性能问题)
虽然可以创建空对象后用 obj.__proto__ = original.__proto__ 强行设置原型,但 __proto__ 是已废弃的非标准属性,V8 等引擎对其优化差,且在严格模式下可能报错。应始终优先使用 Object.setPrototypeOf(newObj, proto) 或 Object.create(proto)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










