最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何利用 Object.create Object.getPrototypeOf 实现具备相同原型结构的深克隆
时间:2026-06-07 10:28:52 编辑:袖梨 来源:一聚教程网
Object.create(Object.getPrototypeOf(obj))仅创建继承原对象原型的空对象,不复制任何属性,因此不是深克隆。真正保留原型的深克隆需先递归拷贝所有属性(含symbol、getter/setter等),再设置新对象原型为原对象原型。
Object.create(Object.getPrototypeOf(obj)) 本身只能创建一个**新对象并继承原对象的原型链**,它不复制属性,更不是深克隆。把它当作“深克隆方法”是一种常见误解。
它实际做了什么
这行代码只完成两件事:
- 获取 obj 的原型对象(即 obj.__proto__ 或 Object.getPrototypeOf(obj))
- 用这个原型对象作为新对象的 [[Prototype]],创建一个**空的新对象**(没有自有属性)
结果是:新对象和原对象共享同一原型链,但所有数据属性(如 {a: 1, b: {c: 2}} 中的 a 和 b)都完全没被复制——新对象是空的。
为什么它不能实现深克隆
深克隆要求:
- 递归复制所有可枚举/不可枚举的自有属性(包括 symbol 属性)
- 对嵌套对象、数组、日期、正则等内置类型做类型感知的拷贝
- 保持原型关系(可选,但你提到了“相同原型结构”,所以这点需保留)
- 处理循环引用(否则会爆栈)
Object.create(...) 连最基础的属性复制都没做,自然不满足任何一条。
如何真正实现“保留原型的深克隆”
需要分两步:先深拷贝属性值,再把结果对象的原型设为原对象的原型。推荐组合使用:
-
属性拷贝:用
Object.getOwnPropertyDescriptors(obj)获取所有属性描述符(含 getter/setter、writable、enumerable、configurable),再用Object.defineProperties(新对象, descriptors) -
原型设置:用
Object.setPrototypeOf(新对象, Object.getPrototypeOf(obj))或在Object.create创建时传入(但注意:create 只设 [[Prototype]],不设属性) - 递归处理值:对每个属性值判断类型——普通对象/数组递归克隆;Date、RegExp、Map、Set 等需特殊构造;基本类型直接返回;null 和 undefined 不处理;遇到循环引用要缓存已克隆对象
简单示意(无循环引用处理):
function cloneWithPrototype(obj) { if (obj === null || typeof obj !== 'object') return obj; // 创建空对象,原型设为 obj 的原型 const cloned = Object.create(Object.getPrototypeOf(obj)); // 获取所有自有属性描述符 const descriptors = Object.getOwnPropertyDescriptors(obj); // 逐个克隆属性值并定义到新对象 for (const key in descriptors) { const desc = descriptors[key]; if ('value' in desc) { desc.value = cloneWithPrototype(desc.value); // 递归克隆值 } Object.defineProperty(cloned, key, desc); } return cloned;}
更实用的建议
- 日常开发中,优先使用成熟库如
lodash.cloneDeep,它默认保留原型(v4.17+),且健壮处理各种边界 - 若必须手写,不要从
Object.create入手想“一步到位”,而应明确分离“原型继承”和“属性深拷贝”两个职责 - 注意:函数、DOM 节点、Error 实例等无法真正深克隆,只能浅拷贝引用或特殊处理
相关文章
- dnf手游远征怎么玩 dnf手游远征玩法详解 06-10
- dnf手游会出剑魂吗 dnf手游剑魂职业解析 06-10
- 地下城与勇士手游漫游装备怎么选 漫游装备选择攻略分享 06-10
- 回声世代2全成就流程攻略分享 06-10
- 《挖掘者米娜》一周目全成就做法指南 06-10
- dnf手游远古金币怎么刷 dnf手游远古金币获取方法 06-10