js中的浅拷贝和深拷贝的区别
时间: 2023-09-11 17:12:48 浏览: 134
浅拷贝和深拷贝是在JavaScript中用于复制对象的两种不同方式。
浅拷贝是按位拷贝对象,它创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址。因此,如果其中一个对象改变了这个地址,就会影响到另一个对象。浅拷贝只复制对象空间而不复制资源。[1]
深拷贝是创建一个新对象,完全复制原始对象及其所有嵌套的对象和数据。深拷贝会递归地复制对象的所有属性,包括基本类型和引用类型。这意味着,即使原始对象的属性是引用类型,深拷贝也会创建一个新的引用类型对象,而不是共享同一个引用。因此,深拷贝不会受到原始对象的更改的影响。[2]
在JavaScript中,可以使用不同的方法来实现浅拷贝和深拷贝。例如,可以使用逐个成员依次拷贝的方式来实现浅拷贝,或者使用递归的方式来实现深拷贝。还可以使用第三方库如lodash提供的函数来实现深拷贝。[2][3]
总结起来,浅拷贝只复制对象的空间而不复制资源,而深拷贝会递归地复制对象及其所有嵌套的对象和数据,创建一个完全独立的副本。
相关问题
js中浅拷贝和深拷贝的区别
### JavaScript 中浅拷贝与深拷贝的区别
#### 浅拷贝特性
浅拷贝仅复制对象的第一层属性。对于基本数据类型(如 `number`、`string` 和 `boolean`),这表现为值的直接复制;而对于复杂的数据结构(如数组或对象),则只是复制其引用而非实际内容[^2]。
```javascript
// 对于基本类型的浅拷贝
let num1 = 5;
let num2 = num1;
num2 = 10;
console.log(num1); // 输出: 5
// 对象类型的浅拷贝展示
const person1 = {
name: 'Alice',
age: 30,
};
const person2 = Object.assign({}, person1);
person2.age = 40;
console.log(person1.age); // 输出: 30 (未受影响)
// 修改嵌套对象的情况
const user1 = {
profile: { city: 'Beijing' }
};
const user2 = Object.assign({}, user1);
user2.profile.city = 'Shanghai';
console.log(user1.profile.city); // 输出: Shanghai (受到影响)
```
#### 深拷贝特性
相比之下,深拷贝不仅复制最外层的对象,还会递归地处理内部所有的子对象,从而确保源对象及其所有后代都被彻底克隆出来,形成全新的独立副本[^1]。
```javascript
// 使用JSON方法实现简单场景下的深拷贝
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
const employee = {
id: 1,
details: {
department: 'Engineering'
},
};
const clonedEmployee = deepClone(employee);
clonedEmployee.details.department = 'HR';
console.log(clonedEmployee.id === employee.id); // true
console.log(clonedEmployee.details !== employee.details);// true
console.log(employee.details.department); // Engineering
```
值得注意的是,在某些特殊情况下,比如循环引用或是含有不可枚举属性的对象时,简单的基于字符串化的方法可能会失效或者丢失特定行为[^4]。因此实践中也常借助第三方库如 Lodash 的 `cloneDeep()` 来完成更可靠的深拷贝操作。
JavaScript 中浅拷贝和深拷贝的根本区别是什么?
<think>我们正在讨论JavaScript中浅拷贝和深拷贝的根本区别。
浅拷贝(Shallow Copy)和深拷贝(Deep Copy)的主要区别在于它们处理对象引用(即嵌套对象)的方式。
简单来说:
- 浅拷贝:只复制对象的第一层属性,如果属性是引用类型(如对象、数组等),则复制的是引用(内存地址),所以拷贝后的对象和原对象在深层属性上仍然共享同一块内存。
- 深拷贝:递归复制对象的所有层级,创建一个完全独立的副本,修改新对象不会影响原对象。
下面通过代码示例详细说明:</think>### JavaScript 中浅拷贝与深拷贝的根本区别
#### 核心区别
**浅拷贝**只复制对象的第一层属性(引用地址),**深拷贝**递归复制对象的所有层级(创建新对象)。根本差异在于对**引用类型属性**的处理方式:
| 特性 | 浅拷贝 | 深拷贝 |
|--------------|--------------------------------|--------------------------------|
| 复制层级 | 仅第一层 | 所有嵌套层级 |
| 引用类型属性 | 复制引用地址(共享内存) | 创建新对象(完全独立内存) |
| 修改影响 | 影响原对象 | 不影响原对象 |
| 内存消耗 | 低 | 高 |
| 性能 | 快 | 慢(需递归遍历) |
#### 代码演示
```javascript
// 原始对象(包含嵌套引用)
const original = {
a: 1,
b: { inner: 2 },
c: [3, 4]
};
// ========== 浅拷贝示例 ==========
const shallowCopy = Object.assign({}, original);
// 修改浅拷贝对象
shallowCopy.a = 100; // ✅ 不影响原对象(基础类型)
shallowCopy.b.inner = 200; // ❌ 影响原对象(引用类型)
shallowCopy.c.push(5); // ❌ 影响原对象(引用类型)
console.log(original.b.inner); // 输出 200(被修改)
console.log(original.c); // 输出 [3, 4, 5](被修改)
// ========== 深拷贝示例 ==========
const deepCopy = JSON.parse(JSON.stringify(original));
// 修改深拷贝对象
deepCopy.a = 1000; // ✅ 不影响原对象
deepCopy.b.inner = 2000; // ✅ 不影响原对象
deepCopy.c.push(50); // ✅ 不影响原对象
console.log(original.b.inner); // 仍为 200(未改变)
console.log(original.c); // 仍为 [3, 4, 5](未改变)
```
#### 内存结构图解
```
原始对象
┌───────────┐ ┌───────────┐
│ a: 1 │ │ b: ├───►┌────────────┐
│ c: ├───►│ [0]:3 │ │ inner: 2 │
└───────────┘ │ [1]:4 │ └────────────┘
└───────────┘
浅拷贝对象
┌───────────┐ ┌───────────┐
│ a: 100 │ │ b: ├──┐
│ c: ├──┐ │ [0]:3 │ │
└───────────┘ │ │ [1]:4 │ │ 指向同一内存
│ └───────────┘ │
└─────────────────┘
深拷贝对象
┌───────────┐ ┌───────────┐ ┌────────────┐
│ a:1000 │ │ b: ├───► │ inner:2000 │
│ c: ├───►│ [0]:3 │ └────────────┘
└───────────┘ │ [1]:4 │
│ [2]:50 │
└───────────┘
```
#### 常见浅拷贝方法
1. **扩展运算符**:`{ ...obj }`
2. **Object.assign()**:`Object.assign({}, obj)`
3. **数组方法**:
- `Array.prototype.slice()`
- `Array.prototype.concat()`
4. **特殊对象**:
- `Object.create()`(原型链复制)
- `Array.from()`(数组浅拷贝)
#### 何时使用
- **浅拷贝适用场景**:
- 无嵌套引用结构的简单对象
- 性能敏感且不需要完全隔离的操作
- 需要共享部分状态的设计模式(如观察者模式)
- **深拷贝适用场景**:
- 状态管理(如 Redux reducer)
- 不可变数据更新
- 复杂配置对象的修改
- 防止意外副作用的关键数据
阅读全文
相关推荐














