JavaScript中的深克隆和浅克隆的区别(“浅克隆”和“浅复制”通常指的是同一个概念)

JavaScript中深克隆与浅克隆的核心区别在于对引用类型属性的处理方式。


浅克隆仅复制对象的第一层属性,引用类型属性仍共享内存地址,修改会影响原对象;


深克隆会递归复制所有层级,创建完全独立的新对象。


浅克隆实现简单、性能高,但存在副作用风险;


深克隆更安全但性能开销大。


常见的浅克隆方法包括展开运算符、Object.assign等,深克隆可通过JSON方法或structuredClone()实现。


需要注意的是,"浅克隆"和"浅复制"本质上是同一概念的不同表述。


实际开发中应根据需求选择合适的克隆方式,确保数据操作的安全性和效率。


JavaScript中的深克隆和浅克隆的区别


以下是 JavaScript 中深克隆浅克隆区别的详细对比表格:

比较维度 浅克隆 (Shallow Clone) 深克隆 (Deep Clone)
核心概念 只复制对象的第一层属性。如果属性是基本类型,复制其值;如果属性是引用类型,复制其内存地址(引用) 递归复制对象的所有层级。不仅复制第一层,连对象内部的引用类型属性也会被完整地复制为一个全新的独立对象
对基本类型属性的处理 值复制。新旧对象的基本类型属性完全独立,修改互不影响。 值复制。同样完全独立,修改互不影响。
对引用类型属性的处理 引用复制 。新旧对象的引用类型属性指向同一个内存地址 创建新对象 。递归复制每一层,新旧对象的引用类型属性指向完全不同的内存地址
嵌套对象修改的影响 修改克隆后对象的嵌套对象属性,会直接影响原始对象的对应属性。 修改克隆后对象的嵌套对象属性,不会影响原始对象的任何属性。
是否共享内存 子对象共享内存。 完全不共享内存,完全独立。
实现方式举例 - 展开运算符 (...) - Object.assign() - 数组的 slice()concat() - JSON.parse(JSON.stringify(obj)) (有局限性) - structuredClone() (现代浏览器内置) - 递归函数或第三方库 (如 Lodash 的 _.cloneDeep())
优点 性能好,实现简单,速度快。 克隆出的对象完全独立,修改无副作用,安全可靠。
缺点 内部引用类型数据会相互影响,可能导致意外的副作用。 实现相对复杂,性能开销较大(尤其对象层级很深或包含循环引用时)。

代码示例说明

javascript 复制代码
// 原始对象
const original = {
  name: 'Alice',
  age: 30,
  address: {
    city: 'Beijing',
    zip: '100000'
  }
};

// --- 浅克隆示例 ---
const shallowCopy = { ...original }; // 使用展开运算符进行浅克隆

shallowCopy.age = 31;               // 修改基本类型: 不影响原对象
shallowCopy.address.city = 'Shanghai'; // 修改嵌套对象: 会影响原对象

console.log(original.age);          // 输出: 30 (没变)
console.log(original.address.city); // 输出: 'Shanghai' (被改变了!)
console.log(shallowCopy.address === original.address); // 输出: true (指向同一个地址)

// --- 深克隆示例 ---
const deepCopy = JSON.parse(JSON.stringify(original)); // 使用JSON方法进行深克隆 (有局限性)

deepCopy.age = 32;
deepCopy.address.city = 'Guangzhou';

console.log(original.age);          // 输出: 30
console.log(original.address.city); // 输出: 'Beijing' (没变!)
console.log(deepCopy.address === original.address); // 输出: false (指向不同地址)

JavaScript中的浅克隆和浅复制是一个意思吗


在 JavaScript 中,"浅克隆"(Shallow Clone)和"浅复制"(Shallow Copy)通常指的是同一个概念,这两个术语在大多数技术文档、教程和日常交流中是可以互换使用的。


核心定义

无论是叫"浅克隆"还是"浅复制",它们都指代以下行为:

  1. 创建新对象/数组:会在内存中创建一个新的对象或数组。
  2. 复制第一层属性
    • 如果属性是基本数据类型 (如 number, string, boolean, null, undefined, symbol, bigint),则复制具体的
    • 如果属性是引用数据类型 (如 object, array, function),则复制引用的地址(指针)。
  3. 结果:新对象和原对象指向同一块内存中的嵌套对象。修改新对象中嵌套对象的属性,会影响原对象。

为什么会有两个名字?

  • 语境差异
    • 复制 (Copy):更侧重于数据的操作过程,常用于描述赋值或传输数据的行为(例如 "Copy an array")。
    • 克隆 (Clone):更侧重于创建一个完全独立的副本实体,常用于面向对象编程或组件库中(例如 "Clone a component state")。
  • 习惯用法:在某些中文翻译的技术文章中,译者可能根据个人习惯选择"克隆"或"复制",但英文原文通常都是 "Shallow Copy" 或 "Shallow Clone",指代完全相同的机制。

代码示例验证

无论你怎么称呼它,下面的代码行为是一致的:

javascript 复制代码
const original = {
  name: "Alice",
  details: { age: 25, city: "Beijing" }
};

// 方法 1: 展开运算符 (常被称为浅克隆/浅复制)
const shallowCopy1 = { ...original };

// 方法 2: Object.assign (常被称为浅复制)
const shallowCopy2 = Object.assign({}, original);

// 验证引用是否共享
console.log(shallowCopy1.details === original.details); // true
console.log(shallowCopy2.details === original.details); // true

// 修改嵌套对象
shallowCopy1.details.city = "Shanghai";

// 原对象也被影响了
console.log(original.details.city); // 输出: "Shanghai"

总结

  • 是一个意思吗? 是的。
  • 区别在哪里? 没有实质性的技术区别,只是用词习惯不同。
  • 需要注意什么? 重要的是区分 "浅" (Shallow)"深" (Deep)
    • 浅 (Shallow):只复制一层,嵌套对象共享引用(即你问的这个概念)。
    • 深 (Deep) :递归复制所有层级,完全断开与原对象的联系(需要使用 structuredClone()JSON.parse(JSON.stringify()) 或第三方库如 Lodash 的 cloneDeep)。

所以在阅读文档或与同事沟通时,你可以放心地将它们视为同义词。

相关推荐
喂哟咦5 分钟前
关于用codex两周写了一个epub阅读器这件事
前端·javascript
CDwenhuohuo19 分钟前
前端文件预览
开发语言·前端·javascript
008爬虫实战录35 分钟前
【最新猿人学】 验证码 - 图文点选 文字验证码识别
前端·javascript
一叶飘零晋1 小时前
【(一)Electron 使用之如何用vite+vue3搭建初始框架】
前端·javascript·electron
恶猫2 小时前
网页自动化模拟操作时,模拟真实按键触发事件【终级方案】
前端·javascript·自动化·vue·网页模拟
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_2:(表单分组与高级输入控件实战)
前端·javascript·css·ui·html
千寻girling3 小时前
滑动窗口刷了快一个月(26天)了 , 还没有刷完. | 含(操作系统学什么的Java 后端)
java·开发语言·javascript·c++·人工智能·后端·python
一袋米扛几楼983 小时前
【报错问题】彻底解决 TypeScript 报错 TS2769: No overload matches this call (JWT 篇)
linux·javascript·typescript
牧码岛4 小时前
Web前端之JavaScrip中的Array、Object、Map和Set详解
前端·javascript·web·web前端
533_4 小时前
[pinia] vue3中监听pinia值的变化
前端·javascript·vue.js