Weakmap详解
先看一个例子
let obj = { name: 'toto' } // { name: 'toto' }这个对象能够被读取到,因为obj这个变量名有对它的引用 // 将引用覆盖掉
obj = null // 这个对象将会被从内存中移除,因为我们已经失去了对它所有的引用
再来看另外一个例子
let obj = { name: 'toto' }
let arr = [ obj ] obj = null
在这个例子中,对象{name:'toto'}
不会被从内存中移除,因为数组arr保存了对它的引用
强引用和弱引用之间有什么区别呢?
事实上,javascript中的大多数变量都保存着对一个对象的强引用。比如上面这个数组保存着对对象{name:'toto'}
的强引用
如果一个变量保存着对一个对象的强引用,那么这个对象将不会被垃圾回收,但是如果一个变量只保存着对这个对象的弱引用,那么这个对象将会被垃圾回收
一些变量类型在对象上有一个弱引用,这就是Weakmap
的情况
Weakmap
weakmap
是一个额外的数据存储,它可以让我们从外部(第三方库)扩展或者封装一个对象,而不需要进行垃圾回收的推断,或者能够智能的创建一个缓存函数。
不用担心看不明白,在比较map
和weakmap
之前我将解释并展示它的含义。
Map和Weakmap的比较
使用map,对象会占用内存,可能不会被垃圾回收。Map对一个对象是强引用
let obj = { name: 'toto' }
let mapObj = new Map()
mapObj.set(obj, 'any value') obj = null
mapObj.size() // 1
Weakmap
则是完全不同的,它不会阻止关键对象的垃圾回收
第一条规则,weakmap
只接受object
作为key
,第二条规则是它只保存对对象的弱引用。
let obj = { name: 'toto' }
let weakmapObj = new WeakMap()
weakmapObj.set(obj, 'any value') obj = null
weakmapObj .size() // 0
对象被垃圾回收器删除,因为weakmap在对象{ name: ‘toto’ }上只有弱引用,而这个对象已经没有强引用了。(只有变量obj有保持引用)
何时使用Weakmap?
正如你所看到的,Weakmap
可以用在任何地方
缓存器函数
const cache = new WeakMap() const process = function (obj) {
// 如果输入的值不在缓存器中
if (!cache.has(obj)) {
// 想象一个函数需要很大的内存或者资源
// 当输入相同时,我们不想重复执行bigOperation函数
const result = bigOperation(obj)
// 所以此时执行一次函数并将它的结果存入缓存中
cache.set(obj, result)
}
return cache.get(obj)
} let obj = { /* any object */ }
// 第一次我们没有这个输入作为缓存,所以在第二次的时候我们才不需要执行这个函数,
const firstResult = process(obj)
// 只需要从缓存中取出结果
const secondeResult = process(obj)
// 源对象将被从weakmap中移除
obj = null
使用map
,这个缓存器函数应该将obj对象保存在内存中。
但这将导致内存泄漏!
当我们对一个不再使用的对象保持引用的时候将会造成内存泄漏,所以如果你不再使用对象,请删除它的任何变量引用。
使用weakmap
时我们不应该使用.keys() / .values() /.entries()
,因为我们不知道何时垃圾回收器会移除这个对象。
最后一个例子
动态无泄漏内存的访问计数器
// 访问计数器
let visitsCountMap = new WeakMap() // 增加访问计数
function countUser(user) {
const count = visitsCountMap.get(user) || 0
visitsCountMap.set(user, count + 1)
} let toto = { name: "toto" } countUser(toto) // 计算访问次数 // 将toto对象从内存中移除
toto = null
Weakmap详解的更多相关文章
- SE6新特性之集合Set、Map、WeakSet和WeakMap详解
SE5的时候我们经常用数组或者类数组对象来操作数据,而对于一些使用惯了java之类语言的集合的开发人员来说,总有少了点什么的感觉,SE6提供Set和Map这两个集合.不仅从根本上为一些问题提供了解决方 ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- Python入门-匿名函数,递归函数,主函数
1.三目运算符 对简单的条件语句,可以用三元运算简写.三元运算只能写在一行代码里面 # 书写格式 result = 值1 if 条件 else 值2 # 如果条件成立,那么将 "值1&quo ...
- Spring Boot配置文件加载顺序
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.通过spring.config.location改变配置文件的位置 二.外部配置加载顺序 1.使用命令行参数指定加 ...
- conn username/password@servicename
conn username/password 方式连接的时候,会碰到这样的错误问题 oracle@prd:/home/oracle/impdir$sqlplus /nolog SQL*Plus: Re ...
- 我们可以定向调度某个pod在某个node上进行创建
集群环境:1.k8s用的是二进制方式安装 2.操作系统是linux (centos)3.操作系统版本为 7.2/7.4/7.94.k8s的应用管理.node管理.pod管理等用rancher.k8s令 ...
- RMI反序列化学习
RMI学习 1.RMI简介 RMI(Remote Method Invocation),远程方法调用方法,其实就是本地java虚拟机要调用其他java虚拟机的方法,两个虚拟机可以是运行在相同计算机上的 ...
- nacos集群模式搭建踩坑记录
首先数据库使用的本地的mysql 1.看日志提示no set datasource,使用虚拟机ping本地后发现无法ping通,原因是本地没有关闭防火墙. 2.看日志提示不允许建立数据库连接,原因是r ...
- Python Requests 速通爆肝、这么牛逼的库你还不会用吗?
上网原理 爬虫原理 Get.Post Requests 介绍 安装 常用方法 Http协议 开发者工具网络界面 Response对象 下载保存一张图片.一首音乐 添加Headers发送请求 判断HTT ...
- Linux的软件安装tomcat 以及jdk
因为tomcat的启动需要jdk,所以我们先安装jdk,安装完成后再安装tomcat 具体的文件大家可以到官网下载,下面介绍安装步骤 目录 jdk安装 1.通过xftp或者其他方式将安装包传到我们的L ...
- K8S+Jenkins自动化构建微服务项目(后续)
因为之前写过基于K8S部署jenkins master/slave平台,在这个的基础上构建微服务到K8S集群中 Jenkins-slave构建微服务项目到K8S集群 1.微服务项目上传到git仓库 这 ...
- 项目依赖模块解决、二次封装Response、后台数据库配置、user模块user表设计、前台创建及配置
今日内容概要 二次封装Response 后台数据库配置 user模块user表设计 前台创建及配置 内容详细 补充--项目依赖模块 # 导出项目依赖模块和安装项目依赖模块 第三方模块--->导出 ...