ES6 中的 Map和Set

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

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

而 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 可用的 方法

set(key, value): 向其中加入一个键值对

get(key): 若不存在 key 则返回 undefined

has(key):返回布尔值

delete(key): 删除成功则返回 true, 若key不存在或者删除失败会返回 false

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 的方法

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

has(key)

delete(key)

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 方法可用.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppdfw.html