ES6 Set 和 Map
[ES6] Set 与 Map
Set
Set 类似数组,区别在于一个 Set 中的值都是唯一的,没有重复值。
创建一个 Set
1 |
|
Set 函数可以接受一个数组(或者具有 iterable
接口的其他数据结构)作为参数来初始化。
1 |
|
用 Set 去重
由于 Set 内的值都不重复,因此可以用来去重。
-
数组去重
1
[...new Set(array)]
-
字符串去重
1
[...new Set('ababbc')].join('')
注意点:
-
NaN
在 Set 内部被认为是相等的。 -
对象总是不相等的。
属性和方法
Set 结构的实例有以下属性。
Set.prototype.constructor
:构造函数,默认就是 Set 函数。Set.prototype.size
:返回 Set 实例的成员总数。
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
四个操作方法:
-
Set.prototype.add(value)
:添加某个值,返回 Set 结构本身。 -
Set.prototype.delete(value)
:删除某个值,返回一个布尔值,表示删除是否成功。 -
Set.prototype.has(value)
:返回一个布尔值,表示该值是否为 Set 的成员。 -
Set.prototype.clear()
:清除所有成员,没有返回值。
四个遍历方法:
-
Set.prototype.keys()
:返回键名的遍历器 -
Set.prototype.values()
:返回键值的遍历器 -
Set.prototype.entries()
:返回键值对的遍历器 -
Set.prototype.forEach()
:使用回调函数遍历每个成员
注意:
-
Set 的遍历顺序就是插入顺序
-
keys
,values
,entries
方法返回的都是遍历器对象。因此,由于 Set 结构没有键名只有键值,keys
和values
方法行为一致。 -
entries
返回的遍历器同事包括键名和键值,因此会输出一个包含两项的数组,这两项完全相等。 -
for...of
循环实际上是values
方法 -
...
扩展运算符内部使用的是for...of
方法,也就是values
方法。因此可以用该方式将 Set 展开为数组,从而间接的使用数组的方法,例如map
,filter
1 |
|
WeakSet
与 Set 的区别:
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。
用处:
WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
这里使用 WeakSet 的好处是,foos 对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑 foos,也不会出现内存泄漏。
1 |
|
Map
Map 类似与对象,区别在于,对象只能使用字符串作为键,而 Map 可以使用各种类型的值(包括对象)作为键。
创建一个 Map
1 |
|
Map 可以接受一个数组作为参数,该数组的成员是一个个表示键值对的数组:
1 |
|
实际上是将参数数组遍历,调用了set
方法。
1 |
|
也就是说,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作 Map 构造函数的参数。
1 |
|
注意:只有对同一个对象的引用,Map 结构才将其视为同一个键,也就是说,[1]
与[1]
虽然值相同,但是是两个不同的数组实例,Map 不会将其视为同一个键:
1 |
|
属性和方法
属性:
Map.prototype.size
返回 Map 结构的成员总数
四个操作方法:
-
Map.prototype.set(key, value)
无则生成,有则更新,返回这个 Map 对象,可以链式操作 -
Map.prototype.get(key)
无则返回undefined
-
Map.prototype.has(key)
有返回true
,无返回false
-
Map.prototype.clear()
清空,无返回值
四个遍历方法:
-
Map.prototype.keys()
:返回键名的遍历器。 -
Map.prototype.values()
:返回键值的遍历器。 -
Map.prototype.entries()
:返回所有成员的遍历器。 -
Map.prototype.forEach()
:遍历 Map 的所有成员。
注意:
Map 的遍历顺序为插入顺序
Map 的默认遍历器接口是 entries 方法。
1 |
|
Map 可以通过...
操作符快速转为数组结构,可以变相的使用数组的方法,例如filter
,map
WeakMap
区别:
WeakMap 只接受对象作为键名(null
除外),不接受其他类型的值作为键名。
WeakMap
的键名所指向的对象,不计入垃圾回收机制。
使用场景:
WeakMap
的键所对应的对象,可能会在将来消失。WeakMap
结构有助于防止内存泄漏。
例如:
一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap
结构。当该 DOM 元素被清除,其所对应的WeakMap
记录就会自动被移除。