你还在用乞丐版的深拷贝么
你还在用乞丐版的深拷贝么
乞丐版:JSON.parse(JSON.stringify());
这种写法非常简单,而且可以应对大部分的应用场景,但是它还是有很大缺陷的,比如拷贝其他引用类型、拷贝函数、循环引用等情况。
基础版本
如果是浅拷贝的话,下面的很容易:
function clone(target){let cloneTarget = {};for (const key in target) {cloneTarget[key] = target[key];}return cloneTarget; }
创建一个新的对象,遍历需要克隆的对象,将需要克隆对象的属性依次添加到新对象上,返回。
如果是深拷贝的话,考虑到我们要拷贝的对象是不知道有多少层深度的,我们可以用递归来解决问题,稍微改写上面的代码:
- 如果是原始类型,无需继续拷贝,直接返回
- 如果是引用类型,创建一个新的对象,遍历需要克隆的对象,将需要克隆对象的属性执行深拷贝后依次添加到新对象上。
很容易理解,如果有更深层次的对象可以继续递归直到属性为原始类型,这样我们就完成了一个最简单的深拷贝:
function clone (target) {if (typeof target === 'object') {let cloneTarget = {};for (const key in target) {cloneTarget[key] = clone(target[key])}return cloneTarget;} else {return target;} }
这是一个最基础版本的深拷贝,这段代码可以让你向面试官展示你可以用递归解决问题,但是显然,他还有非常多的缺陷,比如,还没有考虑数组。
考虑数组
在上面的版本中,我们的初始化结果只考虑了普通的object
,下面我们只需要把初始化代码稍微一变,就可以兼容数组了:
function clone(target) {if (typeof target === 'object') {let cloneTarget = Array.isArray(target) ? [] : {};for (const key in target) {cloneTarget[key] = clone(target[key]);}return cloneTarget;} else {return target;} };
循环引用
const target = {field1: 1,field2: undefined,field3: {child: 'child'},field4: [2, 4, 8] }; target.target = target;
解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。
这个存储空间,需要可以存储key-value
形式的数据,且key
可以是一个引用类型,我们可以选择Map
这种数据结构:
- 检查
map
中有无克隆过的对象 - 有 - 直接返回
- 没有 - 将当前对象作为
key
,克隆对象作为value
进行存储 - 继续克隆
function clone(target, map = new Map()) {if (typeof target === 'object') {let cloneTarget = Array.isArray(target) ? [] : {};if (map.get(target)) {return map.get(target);}map.set(target, cloneTarget);for (const key in target) {cloneTarget[key] = clone(target[key], map);}return cloneTarget;} else {return target;} };
接下来,我们可以使用,WeakMap
提代Map
来使代码达到画龙点睛的作用。
为什么要这样做呢?,先来看看WeakMap
的作用:
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。
什么是弱引用呢?
在计算机程序设计中,弱引用与强引用相对,是指不能确保其引用的对象不会被垃圾回收器回收的引用。 一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。
我们默认创建一个对象:const obj = {}
,就默认创建了一个强引用的对象,我们只有手动将obj = null
,它才会被垃圾回收机制进行回收,如果是弱引用对象,垃圾回收机制会自动帮我们回收。
举个例子:
如果我们使用Map
的话,那么对象间是存在强引用关系的:
let obj = { name : 'ConardLi'} const target = new Map(); target.set(obj,'code秘密花园'); obj = null;
虽然我们手动将obj
,进行释放,然是target
依然对obj
存在强引用关系,所以这部分内存依然无法被释放。
再来看WeakMap
:
let obj = { name : 'ConardLi'} const target = new WeakMap(); target.set(obj,'code秘密花园'); obj = null;
如果是WeakMap
的话,target
和obj
存在的就是弱引用关系,当下一次垃圾回收机制执行时,这块内存就会被释放掉。
设想一下,如果我们要拷贝的对象非常庞大时,使用Map
会对内存造成非常大的额外消耗,而且我们需要手动清除Map
的属性才能释放这块内存,而WeakMap
会帮我们巧妙化解这个问题。
https://juejin.cn/post/6844903929705136141#heading-2
你还在用乞丐版的深拷贝么相关推荐
- python四则运算器tkinter_Python基于Tkinter的二输入规则器(乞丐版)
Python 2.7 IDE Pycharm 5.0.3 有想法就去做,等等等等就没机会了 起因 昨天接触了Tkinter框架,之后就迫不及待的想写个计算器出来,结果呢,可想而知了,当初自己犟脾气,掌 ...
- 马斯克把飞船方向盘用在特斯拉新车上!乞丐版80万起
贾浩楠 萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 马斯克随手升级旧车型,特斯拉立刻成车圈科技圈--甚至航天圈热议焦点. 这不,赛车式的方向盘(也有说宇宙飞船样式),现在成了升级后的新 ...
- android平板开箱,安卓平板不行了吗?小米平板4乞丐版开箱体验
安卓平板不行了吗?小米平板4乞丐版开箱体验 2018-11-11 18:50:00 19点赞 12收藏 44评论 由于晚上开箱就顺手拍照了,光线实在不好,请大家见谅 购买理由 购买之路,就是一个不断减 ...
- C#实现乞丐版IOC容器
一.前言 netcore中的容器非常好用,今天我们自己来简单实现一个. 实现容器的核心接口有两个:IServiceCollection.IServiceProvider.其中IServiceColle ...
- 来电通java版_还在玩JAVA版《我的世界》?教你怎么转换存档玩光追!
简介 如果你一直在花时间扩展和开发"我的世界 (Minecraft)" Java 版世界,那下面为你公布一则好消息:此版本现可转换为"我的世界 (Minecraft)&q ...
- java代码实现在Windows中自动连接WiFi(乞丐版)
之前在学校用校园网时每次开机自己都要连接WiFi然后手动登入校园账号,频繁的登入使我萌生了能不能用代码来完成这些操作.说动手就动手,但现在暑假不在学校无法查看校园登入的一些参数,于是打算先实现自动连接 ...
- 正版Xshell 7免费使用,你还在找破解版吗
原文地址:正版Xshell/Xftp免费使用,你还在找破解版吗 想必很多人都和我一样使用一款软件,先是去官网下载.用了一段时间后提示要付费就直接搜破解版接着用. 今天阿福的Xshell就到期了,笔记本 ...
- mac linux 蓝牙键盘,还在纠结Mac版键盘?试试KeyRemap4MacBook吧!
本帖最后由 亦草亦木 于 2013-2-18 02:03 编辑 有时候能在外设区看到坛子里的朋友发帖求适合Mac的键盘,其实键盘这个东西Mac上和PC上真的没有太大的区别,只不过是键盘映射不同,还有就 ...
- 又涨价了!华为 P40系列海外售价曝光:还好国行版友好不少
随着昨日又两款5G旗舰--努比亚红魔5G游戏手机和realme X50 Pro与我们见面,今年的开年旗舰大战基本进入尾声,而要担当压轴重任的,自然是备受关注的华为P40系列新机. 根据华为官方官宣的消 ...
- 仿作小米官网-乞丐版
这几天学习进度落了很多,导致做的时候很不流畅,很多都不会,都要用到后面的浮什么的,所以我用仅存的知识做了个丐版的 完整代码为 <!DOCTYPE html> <html lang=& ...
最新文章
- matlab数组操作
- linux mate桌面主题下载_7款Linux桌面环境推荐,你值得拥有!
- 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)
- Vue使用Element-ui按需引入大坑
- [微积分] 常用定义与公式
- 解决Linux系统在设置alias命令重启后失效的问题
- Java 在方法和作用域内的内部类
- 矩阵的伴随矩阵的伴随矩阵
- 白化滤波器 matlab,白化滤波器-matlab-程序.doc
- 传统安防企业资本运作:找准定位、创新为本
- 1月1日服务器例行维护公告,1月1日服务器例行维护公告(已完成)
- dwf是什么格式文件
- Ubuntu下编译OpenHarmony
- 计算机打印机副机无法打印,打印机共享无法打印怎么办,教您解决电脑打印机共享无法打印...
- matlab分组形式条形图,Matplotlib带标签的分组条形图
- [数字图像处理]图像复原--逆滤波
- [ARM入门]消失的飞思卡尔:MKV30 16位AD采集
- 股票数据-股票免费查询AP
- 汇编语言寻址方式总结
- STC89C52RC的特殊功能寄存器
热门文章
- 三栏式布局详解(代码+图解)
- java char a z_java中,char A,char a的值各是多少?
- android背景置灰,android view置灰(哀悼日)
- 08-微信公众号素材管理
- 【人体骨骼点】算法综述
- 登陆apple pay显示无法登录服务器,apple pay无法添加卡怎么办?未能连接到apple pay的解决方法...
- boseqc35能不能连电脑_求教boseqc35如何连接win10电脑
- 手游传奇架设教程_传奇手游战神引擎架设教程
- java获取手机型号
- 【 直接复制不用下载 】-- 走遍美国总词汇(完整版)