js中的 拷贝对象数组是深拷贝还是浅拷贝
时间: 2025-05-24 15:02:46 浏览: 23
### JavaScript 中对象数组拷贝的深浅性质
#### 浅拷贝与深拷贝的区别
在 JavaScript 中,浅拷贝和深拷贝的主要区别在于它们如何处理嵌套的对象或数组。
- **浅拷贝**仅复制顶层结构中的引用,而不递归地复制内部对象或数组的内容。这意味着如果原始数据中有嵌套对象或数组,在修改这些嵌套部分时会影响副本[^1]。
- **深拷贝**不仅复制顶层结构,还会递归地复制所有嵌套层次的数据,因此即使修改了深层嵌套的部分也不会影响到源数据[^2]。
---
#### 实现方式对比
##### 1. 普通赋值语法 (`=`)
这是最简单的拷贝形式,但它只创建了一个新的引用而不是真正的拷贝。无论是简单数据类型还是复杂数据类型都属于浅拷贝行为。
```javascript
var obj1 = {a: 1, b: {c: 2}};
var obj2 = obj1;
obj2.b.c = 3;
console.log(obj1); // 输出: {a: 1, b: {c: 3}}
```
这种情况下 `obj1` 和 `obj2` 是同一个内存地址上的引用[^4]。
---
##### 2. 使用 `Object.assign()` 方法
该方法可以用于将多个源对象属性合并到目标对象中。对于基本类型的值会执行深拷贝操作;但对于引用类型仍然只是进行浅拷贝。
```javascript
var source = {x: 1, nestedObj: {y: 2}};
var target = {};
Object.assign(target, source);
target.nestedObj.y = 99;
console.log(source); // 输出: {x: 1, nestedObj: {y: 99}} 表明发生了污染
```
这里可以看到虽然外层字段被独立出来,但是内层对象共享同一份实例[^1]。
---
##### 3. 利用扩展运算符 (`...`)
类似于 `Object.assign()` 的功能,它同样适用于扁平化的一级键值对之间做完全分离的操作,而对于深层次则依旧保持原有关系链路不变。
```javascript
const originalArray = [{id: 'A'}, {id: 'B'}];
const newArray = [...originalArray];
newArray[0].id = 'C';
console.log(originalArray);
// 结果仍然是受影响的状态 [{"id":"C"},{"id":"B"}]
```
这再次验证了当涉及复合型变量的时候,默认机制只会形成表面意义上的映射关联而非彻底断开联系[^3]。
---
##### 4. JSON 序列化解序列化法 (JSON.parse(JSON.stringify()))
这种方法通过先转换成字符串再解析回来的方式实现了较为纯粹意义下的深度克隆效果(针对那些能够正常参与json编码解码过程的标准格式而言),不过需要注意的是某些特殊构造比如函数定义、undefined 或者循环依赖都无法妥善保留下来。
```javascript
let complexDataStructureWithFunctionsAndUndefineds = {
name:"John Doe",
age:null,
job:function(){}
};
try{
let clonedVersionViaJsonSerializationDeserializationApproach =
JSON.parse(
JSON.stringify(complexDataStructureWithFunctionsAndUndefineds )
);
}catch(e){
console.error('Error during cloning:',e.message);
}
finally{
console.warn(`The resulting object lacks the function property due to limitations inherent in this approach.`);
}
/* Expected Output:
Warning: The resulting object lacks the function property...
*/
```
尽管如此,只要满足条件限制就可以放心采用此策略来达成目的[^2].
---
##### 5. 自定义递归算法实现真正意义上无损级别的 Deep Copy
为了克服前面提到的各种局限性问题,我们可以编写专门用来解决任意情况需求的手动逻辑版本如下所示:
```javascript
function deepClone(input) {
const primitiveTypes = ['string', 'number', 'boolean', 'null', 'undefined'];
if(primitiveTypes.includes(typeof input)){
return input;
}
if(Array.isArray(input)){
return input.map(item => deepClone(item));
}
if(typeof input === 'object'){
const output = {};
for(let key in input){
if(Object.prototype.hasOwnProperty.call(input,key)){
output[key]=deepClone(input[key]);
}
}
return output ;
}
throw new Error("Unsupported data type encountered while attempting to perform deep clone.");
}
// Example Usage:
const sampleInput={
title:'Example',
details:{
description:'This is an example.',
tags:['example','test']
},
handlerFunction:(param)=>{return param*2;}
};
const safelyClonedOutput=deepClone(sampleInput);
safelyClonedOutput.details.tags.push('clone');
console.log(safeClonedOutput.details.tags.length===sampleInput.details.tags.length ? true : false ); // Should print TRUE indicating no interference between originals and clones.
```
以上代码片段展示了一个通用解决方案框架,它可以有效应对绝大多数实际应用场景的要求[^3].
---
### 总结
综上所述,理解并掌握这两种不同的复制模式及其适用范围至关重要。具体选择哪种取决于当前项目所面临的具体挑战以及预期成果标准等因素考量结果决定最佳实践方案.
阅读全文
相关推荐
















