你知道JSON.stringify()实现拷贝有什么问题吗?

2024-05-03 09:44

本文主要是介绍你知道JSON.stringify()实现拷贝有什么问题吗?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在说 JSON.stringify() 深拷贝之前,我们先说一说深拷贝和浅拷贝的事情吧。

目录

1 为什么要做深拷贝?

2 哪些做法算浅拷贝?

2.1 直接变量赋值

2.2  Object.assign 浅拷贝

3 哪些做法算深拷贝 ?

3.1 JSON.stringify()

3.2  cloneDeep()

3.3 面试的时候要求手动实现 


1 为什么要做深拷贝?

我们知道javascript基本数据类型,是存在栈内存中,复制相对简单,而引用数据类型,则存在堆内存中,引用数据类型实际是把变量指向了一个内存地址。

栈内存不存在内存地址,所以拷贝前后,新的变量可以不影响旧的变量,但堆内存,单纯的拷贝,还是会公用内存地址,所以修改新的引用数据类型变量,旧的还是会被影响到。所以,拷贝引用数据类型变量的时候,就需要新开一个内存地址,让新的变量指向新的内存地址,从而不影响旧的变量。

2 哪些做法算浅拷贝?

2.1 直接变量赋值

比如我们新创建一个变量,进行等号赋值

<script>const obj1 = {name: 'jim',name2: undefined} const obj2 = obj1;obj2.name2 = 'tom';console.log('obj1的改变:', obj1);
</script>

可以发现,我们改变了obj2的name2属性,但obj1也跟着改变了。

2.2  Object.assign 浅拷贝

Object.assign 是一个浅拷贝,我们看一下代码

<script>var obj1 = {name: 'qiaozhi',sister: ['peiqi', 'suxi'],parent: {mother: 'zhumama',father: 'zhubaba'},do: function () {console.log('I want jump nikeng!')}}var obj2 = Object.assign({}, obj1);obj2.name = 'qiaozhi-new';obj2['sister'][0] = 'peiqi-new';obj2['parent']['mother'] = 'zhumama-new';console.log('查看一下obj1::', obj1);</script>

可以看出, 经过Object.assign拷贝后,基本数据变量得到了拷贝,但数组,对象还是会被修改

3 哪些做法算深拷贝 ?

3.1 JSON.stringify()

JSON.stringify() 是比较常用的深拷贝方案,但他对于一些值会被忽略掉,比如undefined,symbol和函数

<script>var obj1 = {name: 'qiaozhi',name2: undefined,sister: ['peiqi', 'suxi'],parent: {mother: 'zhumama',father: 'zhubaba'},do: function () {console.log('I want jump nikeng!')}}var obj2 = JSON.parse(JSON.stringify(obj1));console.log('看看我的深拷贝ojb2:', obj2);
</script>

你看,name2和do这个属性找不到了。虽然如此,这其实对于平时的业务倒是影响不太大。

3.2  cloneDeep()

这个实现需要引入lodash工具

<script>const lodash = require('lodash');var obj1 = {name: 'qiaozhi',name2: undefined,sister: ['peiqi', 'suxi'],parent: {mother: 'zhumama',father: 'zhubaba'},do: function () {console.log('I want jump nikeng!')}}var obj2 = lodash.cloneDeep(obj1)console.log('看看我的深拷贝ojb2:', obj2);</script>

3.3 面试的时候要求手动实现 

面试的时候,很多时候要求你写一个方法,可以实现深度拷贝,代码如下:

function deepClone(obj, hash = new WeakMap()) {if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);// 可能是对象或者普通的值  如果是函数的话是不需要深拷贝if (typeof obj !== "object") return obj;// 是对象的话就要进行深拷贝if (hash.get(obj)) return hash.get(obj);let cloneObj = new obj.constructor();// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {// 实现一个递归拷贝cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;
}

这篇关于你知道JSON.stringify()实现拷贝有什么问题吗?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/956439

相关文章

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringBatch数据写入实现

《SpringBatch数据写入实现》SpringBatch通过ItemWriter接口及其丰富的实现,提供了强大的数据写入能力,本文主要介绍了SpringBatch数据写入实现,具有一定的参考价值,... 目录python引言一、ItemWriter核心概念二、数据库写入实现三、文件写入实现四、多目标写入

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle