前端之深拷贝

前提:

就是在实际开发中,我有一个编辑的弹窗,可以查看和编辑,因为弹窗里面是一个步骤条,点击下一步就要向对应的接口发送请求,考虑到就比如我点击下一步,此次表箱信息其实不需要修改,我要修改的是控制器的信息,那么点击下一步发送请求其实是没有必要的,我就考虑到了进行比对,如果没有变化就直接下一步,不发送请求

我的想法是,在点击编辑时,把变化前的值给一个变量(旧值),然后在点击下一步用现在的值和旧值进行对比

const editDataBox = ref<any>({});
const initialFormData = ref<any>({});
//编辑
const handleEdit = async (data: any) => {editVisible.value = true;
//在弹窗弹出的时候,把传递过来的值给一个变量initialFormData.value=data
editDataBox.value = data;
....
}
const isFormDataEqual = (formData1: any, formData2: any) => {return JSON.stringify(formData1) === JSON.stringify(formData2);
};
//下一步
const editNext = () => {switch (editCurrent.value) {case 1:const formDataChanged = !isFormDataEqual(editDataBox.value, initialFormData.value);if (formDataChanged) {
...
}else{editCurrent.value += 1;
}
}

这是我刚开始的想法,原本我以为就是initialFormData这个值不会变化,然后我发现表单值变化了也没有发送请求,我就输出formDataChanged这个值,发现每次都是false,进而输出initialFormData它的值,就发现它既然是变化后的值,我就想问题在哪里,原因是:

在 JavaScript 中,当你将一个对象赋值给另一个变量时,实际上是将对象的引用赋值给了这个变量,而不是对象本身的拷贝。这意味着,如果你修改了其中一个变量所引用的对象,另一个变量也会受到影响,因为它们引用的是同一个对象。

在你的代码中,initialFormDataeditDataBox 都是使用 ref 创建的响应式对象。当你在 handleEdit 函数中将 data 赋值给 initialFormData.valueeditDataBox.value 时,它们实际上是引用了同一个对象。

因此,当你修改 editDataBox.value 后,initialFormData.value 也会受到影响,因为它们引用的是同一个对象。

为了避免这种情况,你需要确保 initialFormDataeditDataBox 引用的是不同的对象,而不是同一个对象的引用。这就是为什么需要进行深拷贝的原因,因为深拷贝会创建一个新的对象,其值与原始对象相同,但是引用不同,这样就可以独立地修改新对象而不影响原始对象。

我的解决办法是使用 JSON.parse() 和 JSON.stringify() 进行深拷贝,修改后的代码是,加了一个deepCopy函数进行深拷贝

JSON.parse() 和 JSON.stringify()

const editDataBox = ref<any>({});
const initialFormData = ref<any>({});
const deepCopy = (obj: any) => {return JSON.parse(JSON.stringify(obj));
};
//编辑
const handleEdit = async (data: any) => {editVisible.value = true;initialFormData.value = deepCopy(data);
editDataBox.value = data;
....
}
const isFormDataEqual = (formData1: any, formData2: any) => {return JSON.stringify(formData1) === JSON.stringify(formData2);
};
//下一步
const editNext = () => {switch (editCurrent.value) {case 1:const formDataChanged = !isFormDataEqual(editDataBox.value, initialFormData.value);if (formDataChanged) {
...
}else{editCurrent.value += 1;
}
}

使用 Object.assign():

这个方法只能实现浅拷贝,但如果对象的结构比较简单且不包含嵌套对象,也可以考虑使用它 

const deepCopy = (obj) => {return Object.assign({}, obj);
};

 使用递归:

可以编写一个递归函数来遍历对象的所有属性,并对每个属性进行拷贝。这需要一些额外的代码,但也是一个有效的方法。

const deepCopy = (obj) => {if (typeof obj !== 'object' || obj === null) {return obj;}let newObj = Array.isArray(obj) ? [] : {};for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = deepCopy(obj[key]);}}return newObj;
};

使用 Lodash 库 

Lodash 提供了 _.cloneDeep() 方法,可以实现对象的深拷贝。这是一个非常流行且易于使用的方法。

const _ = require('lodash');// 使用 _.cloneDeep() 进行深拷贝
const deepCopy = (obj) => {return _.cloneDeep(obj);
};

深拷贝在编程中几个重要的优势和应用场景: 

  1. 数据独立性: 深拷贝创建了原始对象的完全独立副本,这意味着修改拷贝后的对象不会影响原始对象。这对于需要在多个地方使用同一份数据,但又需要独立修改数据的情况非常有用。

  2. 避免引用问题: 在 JavaScript 中,如果你简单地将一个对象赋值给另一个变量,实际上是将对象的引用传递给了新变量。这意味着如果你修改了新变量中的对象,原始对象也会受到影响。深拷贝可以避免这种问题,因为它创建了一个完全独立的对象,不会共享内存地址。

  3. 数据传递: 在许多情况下,你可能需要将数据传递给其他函数或组件,并且希望确保传递的是数据的副本而不是引用。深拷贝可以确保你传递的是数据的完整副本,而不会影响原始数据。

  4. 数据比较: 当需要比较两个对象是否相等时,深拷贝可以确保比较的是对象的值而不是引用。这在进行单元测试、数据验证或其他需要比较对象的场景中非常有用。

总的来说,深拷贝是一种保护数据完整性和独立性的重要工具,可以帮助避免由于对象共享引起的意外行为,并确保数据在不同部分之间的传递和修改时保持一致。

你学会了吗?

嗯,可能有的朋友还不太了解JSON.parse() 和 JSON.stringify()?我也是一知半解。

我在想应该写在另一篇文章还是写在这里?emmm,还是重新写一个吧,可以点击跳转

最后,我也是刚入行时间不长的前端,如果有写的有什么问题欢迎指正与交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/9805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐 6 个超好用的 iterm2 zsh 插件

大家好啊&#xff0c;今天给大家分享几个我日常使用的 iterm2 插件&#xff0c;每一个都很有用&#xff0c;希望能给帮助你提高使用命令行的效率&#xff5e; zsh-autosuggestions 插件地址&#xff1a;https://github.com/zsh-users/zsh-autosuggestions 效果展示 当你输入…

AI中转站计费平台系统源码一站式解决方案安装说明

AI中转站计费平台系统源码一站式解决方案安装说明 功能 | Features AI 联网功能 AI online searching service 多账户均衡负载 Multi-account load balancing HTTP2 Stream 实时响应功能 HTTP2 Stream real-time response function 节流和鉴权体系 Throttling and authenticati…

【17-Ⅱ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

开源代码分享(28)-含分布式光伏的配电网集群划分和集群电压协调控制

参考文献&#xff1a; [1] Chai Y , Guo L , Wang C ,et al.Network Partition and Voltage Coordination Control for Distribution Networks With High Penetration of Distributed PV Units[J].IEEE Transactions on Power Systems, 2018:3396-3407.DOI:10.1109/TPWRS.2018…

基于微信小程序的校园二手交易平台设计与实现(论文+源码)_kaic

基于微信小程序的校园二手交易平台 设计与实现 摘 要 随着绿色低碳消费和循环经济的理念越来越深入人心,大学生二手商品市场发展迅猛&#xff0c;而大部分二手交易平台运输方式与收售方式对于大学生用户群体并不适用&#xff0c;所以急需一款针对大学生二手商品交易的软件&…

搜索的未来:OpenAI 的 GPT 如何彻底改变行业

搜索的未来&#xff1a;OpenAI 的 GPT 如何彻底改变行业 概述 搜索引擎格局正处于一场革命的风口浪尖&#xff0c;而 OpenAI 的 GPT 处于这场变革的最前沿。最近出现了一种被称为“im-good-gpt-2-chatbot”的神秘聊天机器人&#xff0c;以及基于 ChatGPT 的搜索引擎的传言&am…

WebSocket基础知识

WebSocket是什么&#xff1f; WebSocket 是一种网络通信协议&#xff0c;它提供了全双工通信机制&#xff0c;允许服务器主动向客户端发送消息&#xff0c;而不仅限于响应客户端的请求。它使用类似于 HTTP 的握手来建立连接&#xff0c;然后使用单独的持久连接来进行通信。这种…

kubernetes删除命名空间下所有资源

kubernetes强制删除命名空间下所有资源 在 Kubernetes 中&#xff0c;当一个命名空间处于 Terminating 状态但不会完成删除过程时&#xff0c;通常是因为内部资源没有被正确清理。要强制删除这个命名空间及其所有资源&#xff0c;你可以采取以下步骤&#xff1a; 1. 确认命名空…

cPanel中如何卸载已安装的SSL证书

我使用的Hostease的Linux虚拟主机产品默认带普通用户权限的cPanel面板&#xff0c;由于临时搭建了一个测试的个人的纯静态的网站&#xff0c;不想要安装SSL证书&#xff0c;但是据这边了解HosteaseLinux虚拟主机是只要域名解析指向主机IP&#xff0c;并且绑定到主机&#xff0c…

中国地面气候资料日值数据获取方式

数据简介 环境气象数据服务平台提供了全国大约2100个点位&#xff0c;2000年至2023年的逐日数据。包括气温、气压、湿度、风、降水等要素。 数据基于ECMWF reanalysis-era5-land、reanalysis-era5-single-levels 以及中国2100站点地面气候资料日值观测数据&#xff0c;使用机器…

BBS客户端服务器的编写

根据网络编程中的内容&#xff0c;我们本篇文章将讲解一个bbs通信的项目&#xff0c;首先让我们了解一下什么是bbs. 一、bbs介绍 BBS&#xff0c;即Bulletin Board System的缩写&#xff0c;中文译为“电子公告板系统”或“网络论坛”。它是一个在网络上进行信息交流和讨论的…

Java解决垂直鉴权问题(对垂直权限进行校验)

Java解决垂直鉴权问题&#xff08;对垂直权限进行校验&#xff09; 文章目录 Java解决垂直鉴权问题&#xff08;对垂直权限进行校验&#xff09;前言一、垂直鉴权是什么&#xff1f;二、实现过程1.新建接口权限菜单映射表2.项目初始化时加载接口菜单映射关系3.自定义过滤器拦截…

[C++][数据结构]哈希2:开散列/哈希桶的介绍和简单实现

前言 接着上一篇文章&#xff0c;我们知道了闭散列的弊端是空间利用率比较低&#xff0c;希望今天学习的开散列可以帮我们解决这个问题 引入 开散列法又叫链地址法(开链法)&#xff0c;首先对关键码集合用散列函数计算散列地址**&#xff0c;具有相同地址的关键码归于同一子…

latex algorithm2e 库学习总结

案例1 \documentclass{article}\usepackage{xeCJK} \usepackage[]{algorithm2e} %\usepackage{ctex} % 中文包\begin{document}\renewcommand{\algorithmcfname}{算法} % 把标题设置为“算法” \begin{algorithm…

云衔科技成为卓豪Zoho中国区代理商,开启智能化企业管理新篇章

每一家企业数字化转型&#xff0c;都在寻求通过技术创新实现业务的飞跃。为了更好地服务于中国企业的数字化转型需求&#xff0c;云衔科技荣幸宣布正式成为卓豪Zoho中国区代理商&#xff0c;这一强强联合将为市场带来全新的数字化解决方案与服务体验&#xff0c;共同开启中国企…

鲁教版六年级数学上册-笔记

文章目录 第一章 丰富的图形世界1 生活中的立体图形2 展开和折叠3 截一个几何体4 从三个方向看物体的形状 第二章 有理数及其运算1 有理数2 数轴3 绝对值4 有理数的加法5 有理数的减法6 有理数的加减混合运算7 有理数的乘法8 有理数的除法9 有理数的乘方10 科学计数法11 有理数…

顺序表经典算法OJ题-- 力扣27,88

题1&#xff1a; 移除元素 题2&#xff1a; 合并两个有序数组 一&#xff1a;题目链接&#xff1a;. - 力扣&#xff08;LetCode&#xff09; 思路&#xff1a;&#xff08;双指针法&#xff09; 创建两个变量src&#xff0c;dst 1&#xff09;若src指向的值为val&#xf…

leetcode-字符串的排列-100

题目要求 思路 1.因为只涉及到字符&#xff0c;因此可以进行排序 2.创建临时字符串&#xff0c;当临时字符串temp的长度等于str的长度&#xff0c;作为判出条件。 3.创建一个标记的数组&#xff0c;每次在temp中插入一个字符&#xff0c;便在对应的数组下标设置为1&#xff0c…

国内如何访问 OpenAI 的 api

这个问题甚至我的一些大厂的朋友也不太清楚&#xff0c;所以我觉得有必备写一篇文章来简单盘盘它&#xff0c;希望能帮助到有需要的人 众所周知&#xff0c;由于大陆与 OpenAI 双方互相封锁&#xff0c;大陆是无法直接访问 OpenAI api 的 不过由于 GPT 4 的统治地位&#xff0c…

C++|二叉搜索树

一、二叉搜索树的概念 二叉搜索树又称为二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点的值小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根结…