详解ES6中的Map与Set集合


Posted in Javascript onMarch 22, 2019

集合的概念以及和数组的区别

其实数组也是集合, 只不过数组的索引是数值类型.当想用非数值类型作为索引时, 数组就无法满足需要了.

而 Map 集合可以保存多个键-值对(key-value),  Set 集合可以保存多个元素.

对Map 和 Set 一般不会逐一遍历其中的元素. Map 一般用来存储需要频繁取用的数据,  Set 一般用来判断某个值是否存在其中.

ES 5 中对 Map 和 Set 的模拟方法

在ES 5 中,没有 Set和Map集合, 一般使用对象来模拟这两种集合, 对象的属性作为键(key),  以属性值作为值(value),  即以 property: property-value 来模拟 key-value 的形式. 具体实现如下:

模拟 Map 的键值对集合:

// 创建一个 Map 对象
var map = Object.create(null);

// 添加属性和属性值, 即 添加 key 和 value
map.key1 = 'value 1';
map.key2 = {};

// 取得 key 对应的 value 
console.log(map.key1); // "value 1"
console.log(map.key2); // "Object {}"

模拟 Set :

// 创建一个 Set 对象
var set = Object.create(null);

// 添加属性和属性值, 即 添加 key 并令其值为 true, 即表示这个key存在于集合中
set.key = true;

// 判断 key 是否存在, 然后进行下一步的操作
if(set.key) { ... }

用对象模拟这两种集合的缺陷

由于对象中的属性名必须是字符串, 如果传入的不是字符串则会强制转换成对应的字符串类型

一般使用 if 语句来判断一个 key 是否存在于集合中,  当这个 key 对应的 value 为 false 或者可以被强制转换为 false 时,  则 if 语句认为这个key不存在.但是其实是存在的, 只不过 value = false 而已.

ES6 中的 Map 和 Set 集合

下面正式来讨论这两种集合的特点

Map

Map 中存储的是 key-value 形式的键值对,  其中的 key 和 value 可以是任何类型的,  即对象也可以作为 key . 这比用对象来模拟的方式就灵活了很多

Map 的创建和初始化

可以用new Map()构造函数来创建一个空的 Map

// 创建一个空的 Map 
let map = new Map();

也可以在 Map() 构造函数中传入一个数组来创建并初始化一个 Map. 传入的数组是二维数组, 其中的每一个子数组都有两个元素,  前者会被作为 key,  后者会被作为 value,  这样就形成了一个 key-value 键值对. 例如:

// 用数组来创建一个 非空的 Map 

let array = [ // 定义一个二维数组, 数组中的每子都有两个元素
  ['key1' , 'value 1'],  // key 是 字符串 "key1", value 是字符串 "value 1"
  [{} , 10086] ,     // key 是个对象, value 是数值 10086
  [ 5, {} ]       // key 是个数值类型, value 是对象
];

let map = new Map(array); // 将数组传入 Map 构造函数中

Map 可用的 方法

  1. set(key, value): 向其中加入一个键值对
  2. get(key): 若不存在 key 则返回 undefined
  3. has(key):返回布尔值
  4. delete(key): 删除成功则返回 true,  若key不存在或者删除失败会返回 false
  5. clear(): 将全部元素清除

size 属性, 属性值为 map 中键值对的个数

遍历方法 forEach()

和数组的 forEach 方法类似, 回调函数中都包含3个参数 值, 键, 和 调用这个方法的 Map 集合本身

map.forEach(function(value, key, ownerMap){
  console.log(key, value); // 每对键和值
  console.log(ownerMap === map); // true
});

Set 集合

Set 和 Map 最大的区别是只有键 key 而没有 value,  所以一般用来判断某个元素(key)是否存在于其中.

创建和初始化方法, 和 Map 大同小异

既可以创建一个空 set 也可以用数组来初始化一个非空的set. 和 Map 不同的是, 数组是一维数组, 每个元素都会成为 set 的键.例如:

// 创建一个数组
let array = [1, 'str'];   // 一维数组

// 用数组来初始化 set
let set = new Set(array);

set 的方法

1、add(key): 往set添加一个元素,  如果传入多个参数, 则只会把第一个加入进去

let set = new Set();
set.add(1, 2, 3);
console.log(set.has(1), set.has(2), set.has(3)); // true false false 可以看到只有第一个参数被加入进了 set

2、has(key)
3、delete(key)
4、clear()

遍历方法 forEach

和 Map 的 forEach 方法相似,  回调函数的参数也是3个 (value,  key,  ownerSet). 按道理来说因为 set 中只有 key 没有 value,  那么会掉函数中不应该存在 value 这个参数, 那么为什么这个 value 参数仍然存在呢?可能是因为 数组和 Map 的 forEach 方法的回调函数的参数都是这三个,  如果对于 Set 而改变了参数, 那么就会丢失了一致性. 这个理由......

那么既然没有 value , 那么这个value的值是什么呢?答案是和key 一样.我们可以把value和key 划等号了.下面这段代码可以验证这个说法.

set.forEach(function(value, key, ownerSet){
  console.log(value === key, set === ownerSet);  // true true
});

WeakSet 和 WeakMap

这两个集合比之前的两个集合在名字之前都加上了 Weak,  这个 Weak 可以直译成弱,  这个弱指的是弱引用,  那么前面不带Weak的 Set 和 Map就不弱, 就是强了,  这个强指的是强引用.

与 Set 和 Map 的区别

先说表层的区别:

  • 弱版本集合的 key 只能是对象,  对于 value 的类型没有限制.
  • 弱版本集合没有 forEach 方法, 也没有 for in 方法,  也不能用数组来初始化(会报错).
  • 弱版本可用的方法较少. WeakSet 只有 add, has, delete 方法可用; WeakMap 只有 set, has, get, delete 方法可用.

根本区别

弱版本的集合和它们对应的强版本根本的区别在对于对象的引用的强弱上,  而对象指的是 key 位置的对象, 即以对象为key的情况.

强弱版本对于 key 是对象时的引用机制如下:

将对象设置为 key 时, 就在集合中保存了这个对象的引用. 当这个对象没有其他引用了的时候, 即只有集合还引用着这个对象的时候, 弱类型的集合会放弃对这个对象的引用, 把这个对象从集合里移除, 不让它继续存在于集合中了, 有些“赶尽杀绝”的意思; 但是强类型的集合还会一直保存着对这个对象的引用, 就把它一直放在集合里.这就是 [WeakSet 和 WeakMap] 与 [Set 和 Map] 的根本区别.

要注意的是这个机制只作用于 key , 而 value 位置绑定的对象无论是否还存在别的引用, WeakMap 都不会放弃这个对象.只有这个位置的 key 绑定的对象没有其他引用时, 才会把 key 和 value 都放弃. 决定权在于 key 位置.

弱版本集合的主要用处

若版本集合可以用在需要生命周期管理的地方,例如保存对一个 DOM 对象的引用, 如果一个 DOM 对象使用完毕, 没有其他的引用了, 那么它应该被 垃圾回收,以免产生内存泄漏,那么弱版本的集合就最适合用来保存这样的对象了。

注意:四种集合都是有序的, 即元素被添加进去的顺序就是在内部保存的顺序. 对于用数组来初始化的集合也一样, 按照在数组中的位置依次添加进集合中.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
不用ajax实现点击文字即可编辑的方法
Dec 16 Javascript
Jquery插件 easyUI属性汇总
Jan 19 Javascript
JSONP获取Twitter和Facebook文章数的具体步骤
Feb 24 Javascript
浅谈 javascript 事件处理
Jan 04 Javascript
jQuery使用load()方法载入另外一个网页文件内的指定标签内容到div标签的方法
Mar 25 Javascript
jquery实现实时改变网页字体大小、字体背景色和颜色的方法
Aug 05 Javascript
js HTML5 Ajax实现文件上传进度条功能
Feb 13 Javascript
微信小程序实现选项卡功能
Jun 19 Javascript
vue template中slot-scope/scope的使用方法
Sep 06 Javascript
webpack结合express实现自动刷新的方法
May 07 Javascript
初学node.js中实现删除用户路由
May 27 Javascript
一文搞懂redux在react中的初步用法
Jun 09 Javascript
js控制随机数生成概率代码实例
Mar 21 #Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
Mar 21 #Javascript
详解基于React.js和Node.js的SSR实现方案
Mar 21 #Javascript
javascript中call()、apply()的区别
Mar 21 #Javascript
vue实现微信获取用户信息的方法
Mar 21 #Javascript
vue里如何主动销毁keep-alive缓存的组件
Mar 21 #Javascript
基于node简单实现RSA加解密的方法步骤
Mar 21 #Javascript
You might like
用PHP实现多级树型菜单
2006/10/09 PHP
php实现只保留mysql中最新1000条记录
2015/06/18 PHP
CodeIgniter中使用Smarty3基本配置
2015/06/29 PHP
php使用Imagick生成图片的方法
2015/07/31 PHP
PHP实现下载远程图片保存到本地的方法
2017/06/19 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
2019/12/30 PHP
AJAX 网页保留浏览器前进后退等功能
2011/02/12 Javascript
jQuery.prototype.init选择器构造函数源码思路分析
2013/02/05 Javascript
JS将光标聚焦在文本最后的实现代码
2014/03/28 Javascript
我的Node.js学习之路(一)
2014/07/06 Javascript
JS实现自动定时切换的简洁网页选项卡效果
2015/10/13 Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形菜单
2015/11/30 Javascript
node.js使用cluster实现多进程
2016/03/17 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
2016/05/07 Javascript
javascript RegExp 使用说明
2016/05/21 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
AngularJS 路由详解和简单实例
2016/07/28 Javascript
jQuery实现微信长按识别二维码功能
2016/08/26 Javascript
js和jquery中获取非行间样式
2017/05/05 jQuery
利用10行js代码实现上下滚动公告效果
2017/12/08 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
[jQuery] 事件和动画详解
2019/03/05 jQuery
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
微信小程序实现电子签名并导出图片
2020/05/27 Javascript
Python3如何解决字符编码问题详解
2017/04/23 Python
详解Python中的四种队列
2018/05/21 Python
python实现移位加密和解密
2019/03/22 Python
python爬虫之快速对js内容进行破解
2019/07/09 Python
python gdal安装与简单使用
2019/08/01 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
python函数定义和调用过程详解
2020/02/09 Python
Python拼接字符串的7种方式详解
2020/03/19 Python
承认错误的检讨书
2014/01/30 职场文书
总经理2015中秋节致辞
2015/07/29 职场文书
银行安全保卫工作总结
2015/08/10 职场文书
2016年大学生党员公开承诺书
2016/03/24 职场文书