你知道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

相关文章

Flask解决指定端口无法生效问题

《Flask解决指定端口无法生效问题》文章讲述了在使用PyCharm开发Flask应用时,启动地址与手动指定的IP端口不一致的问题,通过修改PyCharm的运行配置,将Flask项目的运行模式从Fla... 目录android问题重现解决方案问题重现手动指定的IP端口是app.run(host='0.0.

Java实现将byte[]转换为File对象

《Java实现将byte[]转换为File对象》这篇文章将通过一个简单的例子为大家演示Java如何实现byte[]转换为File对象,并将其上传到外部服务器,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言1. 问题背景2. 环境准备3. 实现步骤3.1 从 URL 获取图片字节数据3.2 将字节数组

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

Nginx实现前端灰度发布

《Nginx实现前端灰度发布》灰度发布是一种重要的策略,它允许我们在不影响所有用户的情况下,逐步推出新功能或更新,通过灰度发布,我们可以测试新版本的稳定性和性能,下面就来介绍一下前端灰度发布的使用,感... 目录前言一、基于权重的流量分配二、基于 Cookie 的分流三、基于请求头的分流四、基于请求参数的分

Seata之分布式事务问题及解决方案

《Seata之分布式事务问题及解决方案》:本文主要介绍Seata之分布式事务问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Seata–分布式事务解决方案简介同类产品对比环境搭建1.微服务2.SQL3.seata-server4.微服务配置事务模式1

Python Excel实现自动添加编号

《PythonExcel实现自动添加编号》这篇文章主要为大家详细介绍了如何使用Python在Excel中实现自动添加编号效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍简单的说,就是在Excel中有一列h=会有重复

mysql关联查询速度慢的问题及解决

《mysql关联查询速度慢的问题及解决》:本文主要介绍mysql关联查询速度慢的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql关联查询速度慢1. 记录原因1.1 在一次线上的服务中1.2 最终发现2. 解决方案3. 具体操作总结mysql

SpringBoot接收JSON类型的参数方式

《SpringBoot接收JSON类型的参数方式》:本文主要介绍SpringBoot接收JSON类型的参数方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、jsON二、代码准备三、Apifox操作总结一、JSON在学习前端技术时,我们有讲到过JSON,而在

一文教你解决Python不支持中文路径的问题

《一文教你解决Python不支持中文路径的问题》Python是一种广泛使用的高级编程语言,然而在处理包含中文字符的文件路径时,Python有时会表现出一些不友好的行为,下面小编就来为大家介绍一下具体的... 目录问题背景解决方案1. 设置正确的文件编码2. 使用pathlib模块3. 转换路径为Unicod

Spring MVC跨域问题及解决

《SpringMVC跨域问题及解决》:本文主要介绍SpringMVC跨域问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录跨域问题不同的域同源策略解决方法1.CORS2.jsONP3.局部解决方案4.全局解决方法总结跨域问题不同的域协议、域名、端口