IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> WeakMap -> 正文阅读

[JavaScript知识库]WeakMap

weakMap

含义

weakMap结构与Map结构类似,也是用于生成键值对的集合。

// WeakMap可以使用set方法添加成员
const wm1 = new weakMap();
const key = {foo:1 };
wm1.set(key,2);
wm1.get(key) // 2

// WeakMap也可以接收一个数组
// 作为构造函数的参数
const k1 = [1,2,3];
const k2 = [4,5,6];
const wm2 = new WeakMap([k1,'foo'],'k2,'bar']]);
wm2.get(k2) // 'bar'

WeakMap与Map的区别:
(1)WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。

const map = new WeakMap();
map.set(1,2)
// TypeError:Invalid value used as weak map key
map.set(null,2)
// TypeError:Invalid value used as weak map key
map.set(Symbol(),2)
// TypeError:Invalid value used as weak map key

上面的代码中,如果将数值1和Symbol值作为WeakMap的键名,都会报错。

(2) WeakMap的键名所指向的对象,不计入垃圾回收机制。
WeakMap的设计目的在于,有时候我们想在某个对象上存放一些数据,但是这会形成对于这个对象的引用。请看下面的例子。

const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
[e1,'foo元素'],
[e2,'bar 元素']
];

上面的代码中,e1和e2是两个对象,我们通过arr数组对这两个对象添加一些文字说明。这就形成了arr对e1和e2的引用。
一旦不需要这两个对象,我们就必须手动删除这个引用,否则垃圾回收机制就不会释放e1和e2占用的内存。

// 不需要e1和e2的时候
// 必须手动删除引用
arr[0] = null;
arr [1] = null'

上面这样的写法显然很不方便。一旦忘了写,就会造成内存内存泄露。
WeakMap就是为了解决这个问题二诞生的,它的键名所引用的对象都是弱引用,即垃圾回收机制不该将该引用考虑在内。因此,只要所引用的对象其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用WeakMap。一个典型应用场景是,在网页的DOM元素上添加数据,就可以使用WeakMap结构。当该DOM元素被清除,其所对应的WeakMap记录就会自动被移除。

const wm = new WeakMap();
const element = document.getElementById(;example');
wm.set(element,'some information);
wm.get(element) // "some information

上面的代码中,先新建一个WeakMap实例。然后将一个Dom节点作为键名存入该实例,并将一些附加信息作为键值。一起存放在WeakMap里面。这时,WeakMap里面对element的引用是弱引用,不会被计入垃圾回收机制。

总之,WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄露。注意,WeakMap弱引用的只是键名,而不是键值。键值依然是正常引用。

const wm = new WealMap();
let key = {};
let obj = {foo:1};

wm.set(key,obj);
obj = null;
wm.get(key) // Object {foo:1}

上面的代码中,键值是正常引用。所以,即使在WeakMap外部消除了obj的引用,用WeakMap内部的引用依然存在。

WeakMap 的语法

WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有keys(),values(),entries()方法),也没有size 属性。因为没有办法列出所有键名,某个键名是否存在完全不可测,跟垃圾回收机制是否运行相关。这一刻可以取到键名,下一刻垃圾回收机制突然运行了,这个键名就没了,为了防止出现不确定性,就统一规定不能渠道键名。二是无法清空,即不支持clear方法。因此WeakMap只有四个方法可用:get()、set()、has()、delete()。

const wm = new WeakMap();

wm.size // undefined
wm.forEach() // undefined
wm.clear() // undefined

WeakMap 的用途

WeakMap应用的经典场景就是DOM节点作为键名。下面是一个例子。

let myWeakMap = new WeakMap();

myWeakMap.set(document.getElementById('logo'),
{timeClick:0});

document.getElementById('logo').addEventListener('click',function() {
let logoData = myWeakMap.get(document.getElementById('logo'));
logoData.timeClicked++;
},false);

上面代码中,document.getElementById(‘logo’)是一个DOM节点,每当发生click事件,就更新一下状态。我们将这个状态作为键值放在WeakMap里,对应的键名就是这个节点对象。一旦这个DOM节点删除,该状态就会自动消失,不存在内存泄漏风险。
WeakMap的另一个用处是部署私有属性。

const _counter = new WeakMap();
const _action = new WeakMap();

class Countdown {
constructor(counter,action) {
_count.set(this.coounter);
_action.set(this.action);
}
dec() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this,counter);
if(counter === 0) {
_action.get(this)();
		}
	}
}
const c =new Countdown(2,() => console.log("done'));
c.dec()
c.dec()
// DONE

WeakRef

WeakSet 和WeakMap 是属于弱引用的数据结构,ES2021更进一步,提供了WeaRef对象,用于直接创建对象的弱引用。

let targt = {};
let wr = new WeakRef(target)

上面的示例中,target是原始对象,构造函数WeakRef()创建了一个基于target的新对象wr。这里,wr就是一个weakRef的实例,属于对target的弱引用,垃圾回收机制不会计入这个引用,也就是说,wr的引用不会妨碍原始对象target垃圾回收机制清除。
WeakRef实例对象有一个deref()方法,如果原始对象存在,该方法返回原始对象;如果原始对象已经被垃圾回收机制清除,该方法返回undefined。

let targt = {};
let wr = new WeakRef(target);

let obj = wr.deref();
if(obj) { //target未被垃圾回收机制清除
// ...
}

上面的示例中,deref()方法可以判断原始对象是否已被清除。
弱引用对象的一大用处就是作为缓存,未被清除时可以从缓存中取值,一旦清除缓存就会自动失效。

function makeWeakCached(f) {
  const cache = new Map();
  return key => {
    const ref = cache.get(key);
    if (ref) {
      const cached = ref.deref();
      if (cached !== undefined) return cached;
    }

    const fresh = f(key);
    cache.set(key, new WeakRef(fresh));
    return fresh;
  };
}

const getImageCached = makeWeakCached(getImage);

上面示例中,makeWeakCached() 用于建立一个缓存,缓存里面保存对原始文件的弱引用。
注意,标准规定,一旦使用WeakRef()创建了原始对象的弱引用没那么在本轮时间循环(event loop),原始对象肯定不会被清除,只会在后面的事件循环才会被清除。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:54:08  更:2021-09-19 07:55:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:36:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码