讲师中心 微信公众号
AI工具推荐 视频效率加速

深克隆和浅克隆区别是什么?

胖雪吖_7130

胖雪吖_7130

发布时间:2025-08-30 08:05:01

|

316人浏览过

|

来源于php中文网

原创

深克隆和浅克隆的区别在于拷贝的深度:浅克隆只复制对象第一层属性,嵌套对象共享引用,修改克隆对象会影响原始对象;深克隆递归复制所有层级,生成完全独立的对象。浅克隆速度快,适用于简单结构;深克隆性能开销大,但能保证彻底隔离。选择方式需权衡对象结构、性能和功能需求。

深克隆和浅克隆区别是什么?

深克隆和浅克隆,简单来说,区别就在于拷贝的深度。浅克隆只复制对象的引用,而深克隆会创建一个全新的对象,包括所有嵌套的对象。

浅克隆,速度快,但修改克隆对象会影响原始对象。深克隆,速度慢,但克隆对象和原始对象完全独立。

深克隆和浅克隆的区别是什么?

为什么需要克隆?

克隆,或者说复制对象,在编程中非常常见。想象一下,你有一个复杂的配置对象,需要在多个地方使用,但每个地方可能需要稍微修改一下。如果直接传递原始对象,修改一处就会影响所有地方。这时候,克隆就派上用场了。它允许你创建对象的副本,这样就可以安全地修改副本,而不会影响原始对象。

另外,在处理不可变对象时,克隆也是一种常见的模式。虽然不可变对象本身不能被修改,但我们可以通过克隆来创建一个新的、修改后的对象。

浅克隆的实现方式和局限性

浅克隆,顾名思义,只复制对象的第一层属性。如果对象包含嵌套的对象(例如,对象中的属性也是一个对象),那么浅克隆只会复制嵌套对象的引用,而不是创建一个新的嵌套对象。

在 JavaScript 中,可以使用

Object.assign()
或扩展运算符 (
...
) 来实现浅克隆:

const originalObject = {
  name: 'Original',
  details: {
    age: 30
  }
};

// 使用 Object.assign() 浅克隆
const shallowClone1 = Object.assign({}, originalObject);

// 使用扩展运算符浅克隆
const shallowClone2 = { ...originalObject };

shallowClone1.name = 'Clone1';
shallowClone1.details.age = 35; // 注意:这里会影响 originalObject

console.log(originalObject.name); // 输出 "Original"
console.log(originalObject.details.age); // 输出 35,被修改了!

可以看到,修改

shallowClone1.name
不会影响
originalObject.name
,因为
name
是原始对象的第一层属性。但是,修改
shallowClone1.details.age
会影响
originalObject.details.age
,因为
details
是一个嵌套对象,浅克隆只复制了它的引用。

这就是浅克隆的局限性:它只能保证第一层属性的独立性,对于嵌套对象,克隆对象和原始对象仍然共享同一个引用。

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载

深克隆的实现方式和性能考量

深克隆会递归地复制对象的所有属性,包括嵌套对象,从而创建一个完全独立的对象。实现深克隆的方法有很多种,其中最简单粗暴的方式是使用

JSON.parse(JSON.stringify(object))
:

const originalObject = {
  name: 'Original',
  details: {
    age: 30
  }
};

// 使用 JSON.parse(JSON.stringify()) 深克隆
const deepClone = JSON.parse(JSON.stringify(originalObject));

deepClone.name = 'DeepClone';
deepClone.details.age = 40;

console.log(originalObject.name); // 输出 "Original"
console.log(originalObject.details.age); // 输出 30,没有被修改!

这种方法简单易懂,但是存在一些问题:

  • 无法处理循环引用: 如果对象中存在循环引用(例如,对象 A 的属性指向对象 B,而对象 B 的属性又指向对象 A),
    JSON.stringify()
    会抛出错误。
  • 无法处理函数和
    undefined
    :
    JSON.stringify()
    会忽略函数和值为
    undefined
    的属性。
  • 性能问题: 对于大型对象,
    JSON.stringify()
    和
    JSON.parse()
    的性能开销比较大。

更健壮的深克隆实现需要递归地遍历对象的属性,并根据属性的类型进行不同的处理。例如,对于基本类型,直接复制值;对于对象类型,递归调用深克隆函数;对于数组类型,创建一个新的数组并递归复制数组中的元素。

function deepClone(obj, cache = new WeakMap()) {
  if (obj === null || typeof obj !== "object") {
    return obj;
  }

  if (cache.has(obj)) {
    return cache.get(obj);
  }

  let clonedObj = Array.isArray(obj) ? [] : {};
  cache.set(obj, clonedObj);

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clonedObj[key] = deepClone(obj[key], cache);
    }
  }

  return clonedObj;
}

const originalObject = {
  name: 'Original',
  details: {
    age: 30
  },
  func: function() { console.log("hello"); },
  arr: [1, 2, 3]
};

originalObject.circularReference = originalObject; // 添加循环引用

const deepCloneObject = deepClone(originalObject);

deepCloneObject.name = 'DeepClone';
deepCloneObject.details.age = 40;
deepCloneObject.arr.push(4);

console.log(originalObject.name); // 输出 "Original"
console.log(originalObject.details.age); // 输出 30
console.log(originalObject.arr); // 输出 [1, 2, 3]
console.log(deepCloneObject.func); // 输出 undefined,函数没有被克隆
console.log(deepCloneObject.circularReference === deepCloneObject); // true,循环引用被正确处理

这个实现使用

WeakMap
来缓存已经克隆过的对象,从而避免循环引用导致的无限递归。它也能够处理函数和
undefined
,但需要注意的是,函数通常不会被深克隆,因为复制函数的行为通常没有意义。

深克隆的性能开销比浅克隆大得多,因为它需要递归地遍历对象的所有属性。在选择克隆方式时,需要根据实际情况权衡性能和功能需求。如果对象结构简单,或者只需要复制第一层属性,那么浅克隆可能就足够了。如果对象结构复杂,或者需要保证完全的独立性,那么就需要使用深克隆。

如何选择合适的克隆方式?

选择深克隆还是浅克隆,取决于你的具体需求。

  • 对象结构: 如果对象结构简单,只有一层属性,那么浅克隆就足够了。如果对象包含嵌套对象,并且你需要修改克隆对象而不影响原始对象,那么就需要深克隆。
  • 性能: 浅克隆速度快,深克隆速度慢。如果性能是关键因素,那么应该尽量避免使用深克隆。
  • 对象类型: 某些类型的对象(例如,函数)可能无法被深克隆。在这种情况下,你需要手动处理这些对象。
  • 可维护性: 深克隆的实现通常比浅克隆复杂,因此需要更多的维护成本。

总而言之,在选择克隆方式时,需要综合考虑对象结构、性能、对象类型和可维护性等因素。

克隆在实际开发中的应用场景

克隆在实际开发中有很多应用场景。

  • 状态管理: 在 React、Redux 等状态管理框架中,经常需要使用克隆来创建新的状态对象,从而避免直接修改原始状态。
  • 数据缓存: 可以使用克隆来创建数据的缓存副本,以便在需要时快速访问数据。
  • 撤销/重做: 可以使用克隆来保存对象的历史状态,从而实现撤销和重做功能。
  • 并发编程: 在并发编程中,可以使用克隆来创建线程安全的对象副本。

克隆是一种非常有用的技术,可以帮助我们更好地管理对象的状态,提高代码的可靠性和可维护性。

热门AI工具

更多
PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2195

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3482

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1176

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

3999

2025.09.10

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6204

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3164

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

1832

2025.10.17

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4458

2023.08.10

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 12.3万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn