es6中的setmap和weakmap

ESnail ESnail     2022-09-03     511

关键词:

ES6 新增了几种集合类型,本文介绍 SetMap 和 WeakMap。比较新的 Firefox、Chrome(需要在 about:flags 启用实验性 JavaScript)以及 IE11 都有不同程度的实现。需要注意的是,ES6 规范会一直调整,本文只以当前规范及浏览器实现为准。

Set(数组基础数据去重)

Set 是 ES6 新增的有序列表集合,它不会包含重复项。之前我们通常用对象(Object)或者数组(Array)来实现没有重复项的集合。但对象会对 key 进行 toString() 操作,这会导致某些 key 会意外覆盖之前的数据;如果 key 本身是一个对象,toString() 也得不到想要的结果,如下:

JSvar o = {};

var key1 = 2;
var key2 = { toString : function() { return 2 } };

var key3 = { x : 1 };
var key4 = { y : 2 };

o[key1] = 1;
o[key2] = 2;
o[key3] = 3;
o[key4] = 4;

// o : Object {2: 2, [object Object]: 4}

数组可以存放任何类型的数据,不过数据除重需要自己实现。

Set 支持 add(item) 方法,用来向 Set 添加任意类型的元素,如果已经添加过则自动忽略;has(item) 方法用来检测 Set 中是否存在指定元素;delete(item) 方法用来从 Set 中删除指定元素;clear() 用来清空 Set;获取 Set 集合长度用 size 属性。如下:

JSvar set = new Set();
set.add(window);
set.has(window); // true
set.size; // 1
set.add(window);
set.add(1);
set.size; // 2
set.delete(window);
set.has(window); // false
set.clear();
set.size; // 0

Set 调用 add、has、delete 等方法时对 key 进行的比较,不做类型转换。可以认为使用「===」进行比较,当然也不全是「===」:

  • Set 中,NaN 只能添加一次(虽然NaN === NaN 返回 false);
  • Set 中,「-0」和「0 或 +0」可以同时存在,因为符号不一样(虽然 -0 === 0 或 -0 === +0 返回 true);

Map(有序键值对集合)

Map 是 ES6 新增的有序键值对集合。键值对的 key 和 value 都可以是任何类型的元素。通过 set(key, value) 方法为 Map 设置新的键值对,如果设置的 key 已经存在则用新的 value 覆盖,Map 在比较 key 时也不做类型转换,跟 Set 类似;Map 的 get(key) 方法用来获取指定 key 的值;Map 的 has(key) 、 delete(key) 、clear() 这些方法和 size 属性,与 Set 类似,直接看代码:

JSvar map = new Map();
var key1 = {toString : function() { return 2}};
var key2 = 2;
map.set(key1, 1);
map.set(key2, 2);

map.has(key1); // true
map.has(‘2‘); // false,类型不同
map.delete(2);
map.size; // 1
map.get(key2); // undefined

迭代

我们没办法像数组一样用 for 循环来迭代 Set,也没办法像对象一样用 for...in 来迭代 Map。但是可以用 ES6 提供的新方法 for...of 来遍历它们。

Set 和 Map 有几个方法会返回可迭代对象(Iterator Objects),分别是 entries()、keys() 和 values()。直接遍历 Set/Map,等同于遍历 entries();keys() 和 values() 则分别返回 key 和 value 的集合;对于 Set,key 和 value 是一样的。这些方法和 for...of 现阶段都只有 Firefox 支持,下面的例子需要在 Firefox 下运行:

JSvar set = new Set();
set.add(‘this is a demo.‘);
set.add(window);
set.add(top);

for(let item of set) {
    console.log(item);
}

WeakMap(非空键值对集合)

WeakMap 相对于普通的 Map,也是键值对集合,只不过 WeakMap 的 key 只能是非空对象(non-null object)。WeakMap 对它的 key 仅保持弱引用,也就是说它不阻止垃圾回收器回收它所引用的 key。WeakMap 最大的好处是可以避免内存泄漏。一个仅被 WeakMap 作为 key 而引用的对象,会被垃圾回收器回收掉。

WeakMap 拥有和 Map 类似的 set(key, value) 、get(key)、has(key)、delete(key) 和 clear() 方法,但没有 size 属性,也没有任何与迭代有关的方法。

为了演示 WeakMap 与内存回收的关系,我用 IE11 做了一个简单的测试。IE11 的 F12 开发者工具改进很大,下次找机会单独介绍。测试流程如下:

  1. 创建一个全局的 Map/WeakMap 对象;
  2. 进入局部作用域,创建大量对象作为 key,加到 Map/WeakMap 中;
  3. 离开局部作用域,检查第 2 步创建的大量对象是否被回收;
  4. 手动回收 Map/WeakMap 对象;

内存使用结果如下:

技术分享

红线位置即为测试的第 2 步,可以看到给 Map/WeakMap 添加大量对象后,内存使用大幅增加;但 WeakMap 没有阻止这些对象随后被回收,内存使用马上跌落,与 Map 对比非常明显;最后手动回收 Map/WeakMap 之后,全部内存都会被回收。

WeakSet?

ES6 还定义了另外一种集合类型:WeakSet,但目前还没有浏览器实现。顾名思义,它应该是没有 size 属性、不能迭代的 Set;且只能添加非空对象。这里有 V8 引擎实现 WeakSet 的代码,可以先看看。

 

es6中的setmap数据结构

  Map、Set都是ES6新的数据结构,他们都是新的内置构造函数。也就是说typeof的结果,多了两个。他们是什么:  Set是不能重复的数组。  Map是可以任何东西当做键的对象;  ES6提供了新的数据结构Set。... 查看详情

es6:数据结构set和map&weakset和weakmap(代码片段)

ES6:数据结构Set和Map&WeakSet和WeakMapSet基本使用常见方法WeakSetWeakSet的特点基本使用WeakMap的应用Map基本使用常见方法WeakMapWeakMap的特点强引用和弱引用在ES6以前存储数据的结构有两种:数组和对象。在ES6中新增两种数据结构:Set... 查看详情

es6:数据结构set和map&weakset和weakmap(代码片段)

ES6:数据结构Set和Map&WeakSet和WeakMapSet基本使用常见方法WeakSetWeakSet的特点基本使用WeakMap的应用Map基本使用常见方法WeakMapWeakMap的特点强引用和弱引用在ES6以前存储数据的结构有两种:数组和对象。在ES6中新增两种数据... 查看详情

es6weakmap和weakset的使用场景

...决这个问题,ES6还引入了另外两种新的数据结构,即称为WeakMap和WeakSet的弱集合。这些集合之所以是“弱的”,是因为它们允许从内存中清除不再需要的被这些集合所引用的对象。 查看详情

EcmaScript5 中的 WeakMap 实现?

】EcmaScript5中的WeakMap实现?【英文标题】:WeakMapimplementationinEcmaScript5?【发布时间】:2013-04-2806:36:48【问题描述】:我遇到了一个在ES5中实现跨浏览器WeakMap的JavaScriptlibrary。(WeakMap计划用于ES6。)如果没有JavaScript语言本身的支... 查看详情

es6map,set和weakmap,weakset

这些是新加的集合类型,提供了更加方便的获取属性值的方法,不用像以前一样用hasOwnProperty来检查某个属性是属于原型链上的呢还是当前对象的。同时,在进行属性值添加与获取时有专门的get,set 方法。//Setsvars=newSet();s.add... 查看详情

ES6 WeakMap 的实际用途是啥?

】ES6WeakMap的实际用途是啥?【英文标题】:WhataretheactualusesofES6WeakMap?ES6WeakMap的实际用途是什么?【发布时间】:2015-06-0710:10:40【问题描述】:ECMAScript6中引入的WeakMap数据结构的实际用途是什么?由于弱映射的键创建了对其对应... 查看详情

map和weakmap数据结构

Map和WeakMap是ES6新增的数据结构一、Map它们本质与对象一样,都是键值对的集合,但是他们与Object对象主要的不同是,键可以是各种类型的数值,而Object对象的键只能是字符串类型或者Symbol类型值,Map和WeakMap是更为完善的Hash结构... 查看详情

javascript中的weakmap和weakset(代码片段)

WeakMap的key不能是基本类型letweakMap=newWeakMap();letobj=;weakMap.set(obj,"ok");//worksfine(objectkey)//can'tuseastringasthekeyweakMap.set("test","Whoops");//Error,because"test"isnotanobject如果key指向了null,则key会被自动回收letj... 查看详情

es6通过weakmap解决内存泄漏问题(代码片段)

一、Map1.定义Map对象保存键值对,类似于数据结构字典;与传统上的对象只能用字符串当键不同,Map对象可以使用任意值当键。2.语法newMap([iterable])属性size:返回键值对的数量。操作方法set(key,value):设置(新增/更新)键key的值... 查看详情

es6set,weakset,map,weakmap

1.SetSet是一个集合,里面的值都是唯一的,没有重复的。Set中可以是任何数据类型,并且添加数据时会进行严格比较,重复数据无法加入。2.WeakSet弱引用Set。只能存储对象,不能存储其他类型。且只保持对其中对象的弱引用,若... 查看详情

es6----setmap应用场景(代码片段)

1.数组去重2.字符串去重属性:Set.prototype.size:返回Set实例的成员总数。Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。add(value):添加某个值,返回Set结构本身。d... 查看详情

es6初识-(冲突)数据结构

Set的用法元素不能重复--唯一性WeakSetkey值只能是对象没有clear属性Mapletmap=newMap([[‘a‘,123],[‘b‘,456]]);;WeakMapleto={};weakmap.set(o,123);console.log(weakmap.get(o));Map与Array的对比  查看详情

浅析map和weakmap区别以及使用场景(代码片段)

在阅读红宝书时遇到了WeakMap这个关键字,第一次见感觉没啥用,是我见识浅了,其实还是有点用的,有多大我不知道(快跑)希望这一篇文章能让你对Map有更好的理解,或者能够帮你理解Map和WeakMap这... 查看详情

浅析map和weakmap区别以及使用场景(代码片段)

在阅读红宝书时遇到了WeakMap这个关键字,第一次见感觉没啥用,是我见识浅了,其实还是有点用的,有多大我不知道(快跑)希望这一篇文章能让你对Map有更好的理解,或者能够帮你理解Map和WeakMap这... 查看详情

weakmap(代码片段)

WeakMap结构与Map结构类似,用于生成键值对的集合。//WeakMap可以使用set方法添加成员constwm1=newWeakMap();constkey=foo:1;wm1.set(key,2);wm1.get(key)//2//WeakMap也可以接受一个数组,//作为构造函数的参数constk1=[1,2,3];constk2=[4,5,6];constwm2=newWeakMap([[k1... 查看详情

list和setmap的差别迭代器读取数据

packagecollectiondemo;importjava.util.ArrayList;importjava.util.LinkedList;importjava.util.List;publicclassTestIt{publicstaticvoidmain(String[]args){//TODO自动生成的方法存根//常见的集合(线性的集合)//List接口就是线性存储的接口,并且是有 查看详情

setmap

...,元素自动按从小到大排序,multiset可以包含重复元素的setmap是排序的结构体,键值不能重复,multimap允许有重复的键值 set(multiset)map(multimap)头文件<set><map>定义#include<functional>set<int,less<i 查看详情