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)通常指的是同一个概念,这两个术语在大多数技术文档、教程和日常交流中是可以互换使用的。
核心定义
无论是叫"浅克隆"还是"浅复制",它们都指代以下行为:
- 创建新对象/数组:会在内存中创建一个新的对象或数组。
- 复制第一层属性 :
- 如果属性是基本数据类型 (如
number,string,boolean,null,undefined,symbol,bigint),则复制具体的值。 - 如果属性是引用数据类型 (如
object,array,function),则复制引用的地址(指针)。
- 如果属性是基本数据类型 (如
- 结果:新对象和原对象指向同一块内存中的嵌套对象。修改新对象中嵌套对象的属性,会影响原对象。
为什么会有两个名字?
- 语境差异 :
- 复制 (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)。
所以在阅读文档或与同事沟通时,你可以放心地将它们视为同义词。