当前位置: 首页 > ai >正文

JS深拷贝与浅拷贝

在 JavaScript 开发中,数据的复制是一个常见的需求。然而,很多人在使用复制功能时,常常会混淆“深拷贝”和“浅拷贝”的概念,导致代码中出现一些难以察觉的错误。今天,我们就来深入探讨一下深拷贝和浅拷贝的区别。

一、深拷贝与浅拷贝的概念

1. 浅拷贝

浅拷贝是指只复制对象的第一层属性,而不会递归复制对象内部的引用类型属性。换句话说,浅拷贝只复制对象的“表面”属性,如果属性值是一个引用类型(如对象或数组),那么复制的只是引用,而不是引用所指向的实际数据。因此,如果修改了浅拷贝后的对象的引用类型属性,原对象也会受到影响。

2. 深拷贝

深拷贝则是完全复制一个对象,包括对象内部的所有层级。深拷贝会递归地复制对象的每个属性,确保新对象与原对象完全独立,互不影响。这意味着,无论原对象的结构有多复杂,深拷贝后的对象都不会受到原对象的任何影响。

二、浅拷贝的实现方法

1. 直接赋值

直接赋值是最简单的浅拷贝方式,但它并不是真正的拷贝,只是将一个变量的引用赋值给另一个变量。因此,修改任何一个变量都会影响另一个变量。

var stu = {name: 'xiejie',age: 18
};
var stu2 = stu;
stu2.name = "zhangsan";
console.log(stu); // { name: 'zhangsan', age: 18 }
console.log(stu2); // { name: 'zhangsan', age: 18 }

2. Object.assign 方法

Object.assign 方法可以将一个或多个源对象的可枚举属性复制到目标对象中。如果源对象的属性值是引用类型,Object.assign 只会复制引用,而不是引用所指向的实际数据。

const stu = {name: 'xiejie',age: 18,stuInfo: {No: 1,score: 100}
};
const stu2 = Object.assign({}, stu);
stu2.stuInfo.score = 90;
console.log(stu); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 90 } }
console.log(stu2); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 90 } }

3. ES6 扩展运算符

ES6 的扩展运算符(...)也可以实现浅拷贝。它的工作原理与 Object.assign 类似,同样只会复制引用类型属性的引用。

const stu = {name: 'xiejie',age: 18,stuInfo: {No: 1,score: 100}
};
const stu2 = {...stu};
stu2.stuInfo.score = 90;
console.log(stu); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 90 } }
console.log(stu2); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 90 } }

4. 数组的 sliceconcat 方法

对于数组,sliceconcat 方法可以实现浅拷贝。这些方法不会修改原数组,而是返回一个新数组。但如果数组中包含引用类型元素,这些方法只会复制引用。

var arr1 = [1, true, 'Hello', { name: 'xiejie', age: 18 }];
var arr2 = arr1.slice();
arr2[3].age = 19;
console.log(arr1); // [ 1, true, 'Hello', { name: 'xiejie', age: 19 } ]
console.log(arr2); // [ 1, true, 'Hello', { name: 'xiejie', age: 19 } ]

5. jQuery 的 $.extend 方法

在 jQuery 中,$.extend 方法可以实现浅拷贝。如果将第一个参数设置为 false(默认值),则为浅拷贝。

const obj = {name: 'wade',age: 37,friend: {name: 'james',age: 34}
};
const cloneObj = {};
$.extend(cloneObj, obj);
obj.friend.name = 'rose';
console.log(obj); // { name: 'wade', age: 37, friend: { name: 'rose', age: 34 } }
console.log(cloneObj); // { name: 'wade', age: 37, friend: { name: 'rose', age: 34 } }

三、深拷贝的实现方法

1. JSON.parse(JSON.stringify)

这是一种广为人知的深拷贝方法。通过将对象转换为 JSON 字符串,再将字符串解析为对象,可以实现深拷贝。但这种方法有一个缺点:它不能处理函数和正则对象。

const stu = {name: 'xiejie',age: 18,stuInfo: {No: 1,score: 100}
};
const stu2 = JSON.parse(JSON.stringify(stu));
stu2.stuInfo.score = 90;
console.log(stu); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 100 } }
console.log(stu2); // { name: 'xiejie', age: 18, stuInfo: { No: 1, score: 90 } }

2. jQuery 的 $.extend 方法

在 jQuery 中,$.extend 方法也可以实现深拷贝。只需将第一个参数设置为 true,即可实现深拷贝。

const obj = {name: 'wade',age: 37,friend: {name: 'james',age: 34}
};
const cloneObj = {};
$.extend(true, cloneObj, obj);
obj.friend.name = 'rose';
console.log(obj); // { name: 'wade', age: 37, friend: { name: 'rose', age: 34 } }
console.log(cloneObj); // { name: 'wade', age: 37, friend: { name: 'james', age: 34 } }

3. 手写递归方法

如果需要更灵活的深拷贝实现,可以手写递归方法。这种方法可以处理各种复杂的数据结构,包括函数和正则对象。

function deepClone(target) {if (typeof target !== 'object' || target === null) {return target;}if (Array.isArray(target)) {const result = [];for (const item of target) {result.push(deepClone(item));}return result;}if (target.constructor === Date) {return new Date(target);}if (target.constructor === RegExp) {return new RegExp(target);}const result = {};for (const key in target) {result[key] = deepClone(target[key]);}return result;
}
http://www.xdnf.cn/news/10852.html

相关文章:

  • 数据加密标准(DES)解析及代码实现(java)
  • 解决IDEA插件使用Lombok找不到符号问题
  • Transformer核心原理
  • C++实现图形化2048小游戏
  • torch.distributed.launch 、 torchrun 和 torch.distributed.run 无法与 nohup 兼容
  • 如何避免工具过多导致的效率下降
  • Java函数式编程(下)
  • 机器人开发前景洞察:现状、机遇、挑战与未来走向
  • 2024-2025-2-《移动机器人设计与实践》-复习资料-8……
  • 【基础】Unity中Camera组件知识点
  • SpringBoot 和 Spring 的区别是什么?
  • 动物超声波记录仪应用场景和厂家
  • Python训练打卡Day41
  • Spring Bean 为何“难产”?攻克构造器注入的依赖与歧义
  • AI+在线教育系统源码:开发智能化互动网校平台全流程详解
  • 【相机基础知识与物体检测】更新中
  • 【北邮 操作系统】第十三章 I/O系统
  • 高考数学易错考点01 | 临阵磨枪
  • Spine工具入门教程4之网格与权重
  • SpringAI系列 - MCP篇(三) - MCP Client Boot Starter
  • 【C++高级主题】多重继承下的类作用域
  • 面向对象系统中对象交互的架构设计哲学
  • 集成学习之Bagging,Boosting,随机森林
  • Vue3 + Vite:我的 Qiankun 微前端主子应用实践指南
  • 杭州白塔岭画室怎么样?和燕壹画室哪个好?
  • LEAP模型
  • MongoDB-6.0.24 主从复制搭建和扩容缩容详解
  • Java垃圾回收机制深度解析:从理论到实践的全方位指南
  • 【Typst】4.导入、包含和读取
  • 【算法设计与分析】实验——汽车加油问题, 删数问题(算法实现:代码,测试用例,结果分析,算法思路分析,总结)