首页 游戏 软件 资讯 排行榜 专题
首页
前端开发
JavaScript深克隆实现方法 使用Object.create复制对象原型链

JavaScript深克隆实现方法 使用Object.create复制对象原型链

热心网友
60
转载
2026-05-06

如何利用 Object.create(Object.getPrototypeOf(obj)) 实现具备相同原型结构的深克隆

如何利用 Object.create(Object.getPrototypeOf(obj)) 实现具备相同原型结构的深克隆

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

开门见山地说,Object.create(Object.getPrototypeOf(obj)) 这行代码,常被误认为是实现深克隆的捷径。但真相是,它仅仅创建了一个**继承原对象原型链的空壳**,既不复制任何属性,更谈不上深克隆。把它当作“深克隆方法”,是一个流传甚广的误解。

它实际做了什么

让我们拆解一下这行代码的执行过程,它其实只干了两件事:

  • 第一步,获取 obj 的原型对象(也就是 obj.__proto__Object.getPrototypeOf(obj) 指向的那个对象)。
  • 第二步,用这个原型对象作为新对象的 [[Prototype]],创建一个**全新的、空荡荡的对象**——注意,这个新对象没有任何自有属性。

结果就是:新对象和原对象在原型链上确实是“亲戚”,共享同一套继承体系。但原对象身上那些实实在在的数据属性(比如 {a: 1, b: {c: 2}} 里的 ab),一个都没被复制过去。新对象只是个空架子。

为什么它不能实现深克隆

那么,真正的深克隆到底要求什么?标准可不低:

  • 需要递归地复制所有自有属性,无论是可枚举的还是不可枚举的,甚至包括 Symbol 类型的属性。
  • 对嵌套的对象、数组,以及 Date、RegExp 这些内置类型,要有类型识别能力,进行针对性的拷贝。
  • 保持原型关系(既然你提到了“相同原型结构”,那这一点就是必须项)。
  • 妥善处理循环引用,否则递归过程很容易栈溢出。

回头再看 Object.create(...),它连最基础的属性复制这一步都没迈出去,后面的所有高级要求自然也就无从谈起了。

如何真正实现“保留原型的深克隆”

想达到目的,思路必须清晰:分两步走。先深拷贝所有属性值,再为拷贝结果设置正确的原型。一个比较稳妥的组合方案是:

  • 属性拷贝:使用 Object.getOwnPropertyDescriptors(obj) 获取对象所有的属性描述符。这个方法很强大,能拿到包括 getter/setter、可写性(writable)、可枚举性(enumerable)、可配置性(configurable)在内的完整信息。然后,用 Object.defineProperties(新对象, descriptors) 将这些属性定义到新对象上。
  • 原型设置:有两种方式。一是用 Object.setPrototypeOf(新对象, Object.getPrototypeOf(obj)) 事后设置;二是在用 Object.create 创建空对象时就传入原型(但切记,此时属性还是空的,需要后续补充)。
  • 递归处理值:这才是深克隆的核心。对每个属性值进行类型判断——普通对象或数组就递归克隆;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。从 4.17+ 版本开始,它默认就会保留原型,并且已经健壮地处理了各种边界情况,省心又可靠。
  • 如果确实需要手写实现,思路一定要清晰:将“原型继承”和“属性深拷贝”视为两个独立的职责,分别处理,不要试图用 Object.create 一步到位。
  • 最后,必须清醒地认识到,有些东西是无法真正深克隆的,比如函数、DOM 节点、Error 对象实例等。对于这些,通常只能进行浅拷贝引用,或者设计特殊的处理逻辑。
来源:https://www.php.cn/faq/2426544.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

Apple AirPods Pro 3 立减 20%,现在下单仍赶得上母亲节送达
游戏攻略
Apple AirPods Pro 3 立减 20%,现在下单仍赶得上母亲节送达

母亲节临近,各大平台的促销活动早已悄然上线。今年,不妨考虑一份比鲜花更实用、陪伴更持久的礼物。目前,亚马逊和塔吉特百货(Target)正对苹果最新的 AirPods Pro 3 降噪无线耳机进行限时八折促销,到手价仅需199 99美元(原价249美元),并支持免费送货。对于亚马逊Prime会员,还可

热心网友
05.05
如何通过Perplexity订阅获得更好的搜索体验_配置Pro版专属AI设置
AI
如何通过Perplexity订阅获得更好的搜索体验_配置Pro版专属AI设置

如何通过Perplexity订阅获得更好的搜索体验:配置Pro版专属AI设置 AI智能聊天、问答助手、智能搜索,再加上多模态理解能力,这些工具确实能帮你轻松跨越从0到1的创作门槛。但如果你已经订阅了Perplexity Pro版本,却发现搜索结果的专业度不尽如人意,信源控制力偏弱,或者响应延迟明显,

热心网友
05.04
Premiere2018怎么给视频调色-给视频调色的详细步骤分享
电脑教程
Premiere2018怎么给视频调色-给视频调色的详细步骤分享

Premiere 2018视频调色全流程解析 在Premiere Pro 2018中,丰富的工具集让视频剪辑与色彩调整变得游刃有余。如果你正想为视频注入独特的情绪与风格,那么调色无疑是关键一步。下面,就让我们一起拆解在Premiere 2018中完成视频调色的完整操作流程。 Premiere 201

热心网友
05.04
ArcTime Pro时间轴怎么整体平移缩放-时间轴整体平移缩放的详细步骤
电脑教程
ArcTime Pro时间轴怎么整体平移缩放-时间轴整体平移缩放的详细步骤

ArcTime Pro时间轴整体平移与缩放操作详解 在处理视频字幕时,时间轴的精准控制往往是关键一步。不少朋友在操作ArcTime Pro时,可能会遇到这样一个具体问题:如何对时间轴进行整体平移和缩放?这看似简单的操作,其实关系到后续字幕对齐的效率与精确度。下面,我们就来一步步拆解这个功能,手把手带

热心网友
05.04
ArcTime Pro字幕怎么修改样式-字幕修改样式的详细步骤
电脑教程
ArcTime Pro字幕怎么修改样式-字幕修改样式的详细步骤

ArcTime Pro字幕样式修改指南 很多朋友在使用ArcTime Pro时,可能会对如何调整字幕样式感到有些困惑。其实,掌握方法后非常简单。下面这份详细的步骤解析,将带你快速上手,轻松打造出符合心意的字幕效果。 ArcTime Pro字幕怎么修改样式 第一步,自然是启动软件。在电脑上找到并双击“

热心网友
05.04

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

Composer生成vendor离线包详细步骤与实用指南
编程语言
Composer生成vendor离线包详细步骤与实用指南

vendor目录离线包本质是composer install --no-dev后的完整快照 vendor 目录离线包本质是 composer install --no-dev 后的完整快照 Composer vendor目录离线包,本质上是一个经过精简、可直接部署到生产环境的依赖文件夹快照。其核心目

热心网友
05.06
CentOS系统设置PHP定时任务详细步骤
编程语言
CentOS系统设置PHP定时任务详细步骤

在CentOS系统中设置PHP定时任务 对于需要在CentOS服务器上自动化执行PHP脚本的场景,crontab无疑是那个最经典、最可靠的工具。它就像一位不知疲倦的守夜人,能帮你精准地按计划完成任务。下面,我们就来一步步拆解如何配置它。 第一步:确保PHP环境就绪 首先,需要确认您的CentOS系统

热心网友
05.06
CentOS系统安装PHP依赖的详细步骤
编程语言
CentOS系统安装PHP依赖的详细步骤

在CentOS上安装PHP依赖的完整指南 想要在CentOS系统中高效部署PHP扩展?首要步骤并非直接执行安装指令,而是配置好功能强大的“软件源仓库”。EPEL与Remi仓库是构建稳定PHP环境的基石。本教程将详细解析从仓库配置到扩展安装的全流程,助你搭建坚实的PHP运行基础。 安装EPEL仓库 E

热心网友
05.06
CentOS系统配置PHP远程数据库连接教程
编程语言
CentOS系统配置PHP远程数据库连接教程

CentOS系统下PHP远程连接配置指南:基于cURL扩展的完整教程 在CentOS服务器环境中,实现PHP与外部网络资源的远程通信是常见的开发需求。cURL扩展作为PHP内置的强大网络库,能够高效支持HTTP、HTTPS、FTP等多种协议的数据传输。本教程将详细演示如何在CentOS系统上配置并使

热心网友
05.06
CentOS系统下配置vsFTPd服务集成指南
编程语言
CentOS系统下配置vsFTPd服务集成指南

在CentOS上集成vsftpd与其他服务:一份实战指南 将CentOS系统中的vsftpd(Very Secure FTP Daemon)与其他关键服务进行集成,能够大幅增强其功能性、安全性与管理效率。具体的集成方案需根据您的实际业务需求来定制。本文将深入探讨几个最常见的集成场景,并提供清晰、可操

热心网友
05.06