先看一个例子

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是一个额外的数据存储,它可以让我们从外部(第三方库)扩展或者封装一个对象,而不需要进行垃圾回收的推断,或者能够智能的创建一个缓存函数。

不用担心看不明白,在比较mapweakmap之前我将解释并展示它的含义。

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详解的更多相关文章

  1. SE6新特性之集合Set、Map、WeakSet和WeakMap详解

    SE5的时候我们经常用数组或者类数组对象来操作数据,而对于一些使用惯了java之类语言的集合的开发人员来说,总有少了点什么的感觉,SE6提供Set和Map这两个集合.不仅从根本上为一些问题提供了解决方 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. linux三剑客试题汇总

    1.找出/proc/meminfo文件中以s开头的行,至少用三种方式忽略大小写 [root@localhost ~]# grep -E '^[sS]' /proc/meminfo [root@loca ...

  2. Kubernetes部署单元-Pod

    在 k8s 搞出 pod 概念的时候,其实 docker 官方就已经推出自己的容器编排应用 swarm.这一套服务可以帮助在不同节点上的容器,进行统一的管理,主要针对容器的启停,运维,还有部署,注意我 ...

  3. 基于 Apache Hudi 构建增量和无限回放事件流的 OLAP 平台

    1. 摘要 在本博客中,我们将讨论在构建流数据平台时如何利用 Hudi 的两个最令人难以置信的能力. 增量消费--每 30 分钟处理一次数据,并在我们的组织内构建每小时级别的OLAP平台 事件流的无限 ...

  4. 代码源 BFS练习1

    BFS练习1 http://oj.daimayuan.top/course/11/problem/147 题目 思路 四个方向进行BFS 注意:此题读写量大,cin会被卡 代码 #include &l ...

  5. 软件工程web课程第一次实验作业

    开头总结 本次作业使用html+css+js实现了一个简单页面 最终我要记录的是使用js完成了轮播图中图片背景的转换 <script> window.onload = function ( ...

  6. python连接redis、redis字符串操作、hash操作、列表操作、其他通用操作、管道、django中使用redis

    今日内容概要 python连接redis redis字符串操作 redis之hash操作 redis之列表操作 redis其他 通用操作,管道 django中使用redis 内容详细 1.python ...

  7. Atlas2.2.0编译、安装及使用(集成ElasticSearch,导入Hive数据)

    1.编译阶段 组件信息: 组件名称 版本 Atals 2.2.0 HBase 2.2.6 Hive 3.1.2 Hadoop 3.1.1 Kafka 2.11_2.4.1 Zookeeper 3.6. ...

  8. 小米 pro 笔记本双硬盘设置引导盘

    功能键 F2 进入 BIOS F12 进入 Boot 选项 步骤 小米 Pro 默认是开启了 UEFI,如果 Boot 选项没有显示出期望的系统盘,那么就是这个系统盘没有 UEFI 分区,按照这个文档 ...

  9. mybatis plus 的 ActiveRecord 模式

    实体类继承 Model public class Test extends Model<Test> implements Serializable {} 就可以 new Test().in ...

  10. Go基础3:函数、结构体、方法、接口

    目录 1. 函数 1.1 函数返回值 同一种类型返回值 带变量名的返回值 函数中的参数传递 函数变量 1.2 匿名函数--没有函数名字的函数 在定义时调用匿名函数 将匿名函数赋值给变量 匿名函数用作回 ...