详解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 相关文章推荐
js replace 与replaceall实例用法详解
Aug 03 Javascript
用js代码改变单选框选中状态的简单实例
Dec 18 Javascript
JQuery实现动态表格点击按钮表格增加一行
Aug 24 Javascript
JavaScript设计模式之策略模式实例
Oct 10 Javascript
javascript Deferred和递归次数限制实例
Oct 21 Javascript
javascript消除window.close()的提示窗口
May 20 Javascript
判断数组是否包含某个元素的js函数实现方法
May 19 Javascript
深入理解js函数的作用域与this指向
May 28 Javascript
小程序调用微信支付的方法
Sep 26 Javascript
JavaScript将数组转换为链表的方法
Feb 16 Javascript
微信小程序实现上传多张图片、删除图片
Jul 29 Javascript
vue 递归组件的简单使用示例
Jan 14 Vue.js
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 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
2012/12/07 PHP
laravel框架实现敏感词汇过滤功能示例
2020/02/15 PHP
Jquery实战_读书笔记2 选择器
2010/01/22 Javascript
JavaScript window.document的属性、方法和事件小结
2012/10/24 Javascript
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
Javascript开发之三数组对象实例介绍
2012/11/12 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
2015/04/06 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【一】
2016/05/10 Javascript
jQuery基于$.ajax设置移动端click超时处理方法
2016/05/14 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
Bootstrap菜单按钮及导航实例解析
2016/09/09 Javascript
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
2017/10/25 Javascript
vue中父子组件注意事项,传值及slot应用技巧
2018/05/09 Javascript
JavaScript实现选项卡效果的分析及步骤
2019/04/16 Javascript
基于jQuery的时间戳与日期间的转化
2019/06/21 jQuery
JavaScript中clientWidth,offsetWidth,scrollWidth的区别
2021/01/25 Javascript
Python操作MongoDB数据库PyMongo库使用方法
2015/04/27 Python
分享几道你可能遇到的python面试题
2017/07/24 Python
python pandas 对时间序列文件处理的实例
2018/06/22 Python
对Python3.6 IDLE常用快捷键介绍
2018/07/16 Python
Pandas透视表(pivot_table)详解
2019/07/22 Python
解决pyshp UnicodeDecodeError的问题
2019/12/06 Python
python深copy和浅copy区别对比解析
2019/12/26 Python
keras 权重保存和权重载入方式
2020/05/21 Python
Python模拟伯努利试验和二项分布代码实例
2020/05/27 Python
python中slice参数过长的处理方法及实例
2020/12/15 Python
香港草莓网:Strawberrynet香港
2019/05/10 全球购物
你所知道的集合类都有哪些?主要方法?
2012/12/31 面试题
JAVA和C++区别都有哪些
2015/03/30 面试题
中专生自我鉴定书范文
2013/12/28 职场文书
社区工作者感言
2014/03/02 职场文书
优秀团员自我评价范文
2014/04/23 职场文书
幼儿园教师节感谢信
2015/01/23 职场文书
导游词之鲁迅祖居
2019/10/17 职场文书
MySQL 数据丢失排查案例
2021/05/08 MySQL
Django框架之路由用法
2022/06/10 Python