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

JavaScript之深浅拷贝

在 JavaScript 中,对象和数组的复制是开发中常见的操作,但由于基本类型与引用类型的内存存储机制不同,复制行为会呈现出不同的特性。本文将从底层原理出发,详细解析浅拷贝与深拷贝的区别,并通过代码示例演示如何正确实现,帮助开发者避免数据操作中的常见陷阱。

一、基础概念:值类型 vs 引用类型

在理解深浅拷贝之前,必须先明确 JavaScript 中的两种数据类型:

1. 值类型(基本类型)

  • 包括 NumberStringBooleanNullUndefinedSymbolBigInt
  • 特点:数据直接存储在栈内存中,赋值时会创建新的副本
let a = 10;
let b = a; // 栈内存中创建新值 10,b 与 a 互不影响
b = 20;
console.log(a); // 10

2. 引用类型

  • 包括 ObjectArrayFunctionDate 等
  • 特点:栈内存存储对象的引用地址,堆内存存储实际数据
let obj1 = { name: 'Alice' };
let obj2 = obj1; // obj2 与 obj1 指向同一个堆内存地址
obj2.name = 'Bob';
console.log(obj1.name); // 'Bob'(修改会同步影响原对象)

二、直接赋值

开发中我们经常需要复制一个对象,如果直接赋值会有下面问题

直接赋值只是创建了一个新的变量,该变量和原变量指向同一个对象。这意味着两个变量实际上引用的是内存中的同一个对象,无论通过哪个变量对对象进行修改,另一个变量访问的对象也会发生改变。

示例代码如下:

let original = { a: 1, b: { c: 2 } };
let copied = original;copied.a = 10;
copied.b.c = 20;console.log(original.a); // 输出: 10
console.log(original.b.c); // 输出: 20

在这个例子中,copied 变量和 original 变量指向的是同一个对象,因此修改 copied 也会影响到 original


深浅拷贝只针对引用类型


三、浅拷贝(Shallow Copy)

1. 核心定义

  • 创建一个新对象,浅层复制原对象的属性
  • 对于基本类型属性:复制值本身(独立副本)
  • 对于引用类型属性:复制引用地址(新旧对象共享同一堆内存)

2.实现方法

⑴.展开运算符 ...

        const obj = {uname: 'pink',age: 18}const o = { ...obj }console.log(o)o.age = 20console.log(o)console.log(obj)

⑵.Object.assgin( )

        const obj = {uname: 'pink',age: 18}const o = {}Object.assign(o, obj)console.log(o)o.age = 20console.log(o)console.log(obj)

3.浅拷贝,拷贝的是地址

        const obj = {uname: 'pink',age: 18,family: {baby: '小pink'}}const o = {}Object.assign(o, obj)console.log(o)o.age = 20o.family.baby = '老pink'console.log(o)console.log(obj)

  • 创建一个新对象,浅层复制原对象的属性
  • 对于基本类型属性:复制值本身(独立副本)
  • 对于引用类型属性:复制引用地址(新旧对象共享同一堆内存)

四、深拷贝(Deep Copy)

1. 核心定义

  • 创建一个完全独立的新对象,递归复制原对象的所有层级属性
  • 无论基本类型还是引用类型,新对象与原对象在内存中完全隔离

2.常见方法:

⑴方法①:递归实现深拷贝

原理:手动遍历对象的每一层,递归复制所有基本类型和引用类型。

function deepClone(obj) {if (typeof obj !== 'object' || obj === null) {return obj; // 如果是基本类型或null,直接返回}const clone = Array.isArray(obj) ? [] : {}; // 判断是数组还是对象for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key]); // 递归复制嵌套属性}}return clone;
}// 测试例子
const original = { a: 1, b: { c: 2 } };
const copy = deepClone(original);
copy.b.c = 999;
console.log(original.b.c); // 输出 2(原对象未被修改)

缺点

  • 无法处理特殊对象(如 Date、RegExp)。

  • 无法处理循环引用(如 obj.self = obj 会栈溢出)。

⑵方法②:使用 Lodash 的 cloneDeep

原理:Lodash 是一个流行的工具库,它的 cloneDeep 方法可以处理各种复杂对象的深拷贝。

  1. 安装并引入 Lodash:

npm install lodash

使用示例:

const _ = require('lodash');const original = { a: 1, b: { c: 2 } };
const copy = _.cloneDeep(original);copy.b.c = 999;
console.log(original.b.c); // 输出 2(原对象未被修改)

优点

  • 支持所有数据类型(包括 Date、RegExp 等)。

  • 处理循环引用不会报错。

⑶方法③:通过 JSON.stringify() 实现

原理:将对象转为 JSON 字符串,再解析回对象,间接实现深拷贝。

const original = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(original));copy.b.c = 999;
console.log(original.b.c); // 输出 2(原对象未被修改)

缺点

  • 无法复制函数、undefined、Symbol 等特殊类型。

  • 会丢失 Date 对象(转为字符串)。

  • 循环引用会报错(如 obj.self = obj)。

方法优点缺点
递归实现无需依赖第三方库无法处理复杂对象和循环引用
Lodash.cloneDeep功能强大,支持所有数据类型需要安装第三方库
JSON.stringify简单快速丢失函数、特殊类型,不支持循环引用

http://www.xdnf.cn/news/75295.html

相关文章:

  • 安宝特方案 | 医疗AR眼镜,重新定义远程会诊体验
  • 【安装部署】Linux下最简单的 pytorch3d 安装
  • 安宝特案例 | AR如何大幅提升IC封装厂检测效率?
  • C#进阶学习(十)更加安全的委托——事件以及匿名函数与Lambda表达式和闭包的介绍
  • 【架构】ANSI/IEEE 1471-2000标准深度解析:软件密集型系统架构描述推荐实践
  • 【MATLAB第117期】#源码分享 | 基于MATLAB的SSM状态空间模型多元时间序列预测方法(多输入单输出)
  • 4.21—4.22学习总结 JavaWeb:HTML-CSS
  • Laravel 对接阿里云 OSS 说明文档
  • ecovadis评级范围,如何拿到ecovadis评级高分
  • K8S探针的应用
  • 【教程】安装 iterm2 打造漂亮且高性能的 mac 终端
  • k8s-1.28.10 安装metrics-server
  • 模拟实现strncat、qsort、atoi
  • AR/VR衍射光波导性能提升遇阻?OAS光学软件有方法
  • 如何将当前文件夹及其子文件夹下的所有word提取到一个excel里
  • 新能源汽车充电桩:多元化运营模式助力低碳出行
  • CoinNexus Chain 推出泰利风暴,开启 Web3.0 智能金融元宇宙科技新时代
  • 数字空间与VR有什么关系?什么是数字空间?
  • 全能 Sui 技术栈,构建 Web3 的未来
  • Go语言之sync包 WaitGroup的使用和底层实现
  • NVIDIA 自动驾驶技术见解
  • 基于监督学习的图像分类系统优化
  • Oracle--PL/SQL编程
  • 蓝桥杯常考的找规律题
  • Unity Paint In 3D 入门
  • (51单片机)LCD显示温度(DS18B20教程)(LCD1602教程)(延时函数教程)(单总线教程)
  • PDF处理控件Aspose.PDF指南:使用 Python 将 EPUB 转换为 PDF
  • Kubernetes相关的名词解释kubelet 组件(17)
  • uniapp 上传二进制流图片
  • DeepSeek和Excel结合生成动态图表