Map|Set|WeakMap|WeakSet
Map
Map 是一个带键(键是唯一的)的数据项的可迭代、有序集合(它会记住键的插入顺序)。使用Map构造函数可以传入一个带有键值对的数组(或其它可迭代对象)来进行初始化。
info
Map 使用 SameValueZero 算法 来比较键是否相等。它和严格等于 ===
差不多,但区别是 NaN
被看成是等于 NaN
。所以 NaN
也可以被用作键。这个算法不能被改变或者自定义。
Map的方法和属性
new Map([iterable])
—— 创建 map,入参(可选)为一个元素是键值对的数组或其他可迭代对象(例如,包含两个元素的数组,如[[ 1, 'one' ],[ 2, 'two' ]]
)每个键值对都被添加到新的 Map 中。map.set(key, value)
—— 根据键存储值。每一次map.set
调用都会返回map
本身,所以我们可以进行“链式”调用:map.set('1', 'str1').set(1, 'num1').set(true, 'bool1');
map.get(key)
—— 根据键来返回值,如果 map 中不存在对应的 key,则返回undefined
。map.has(key)
—— 如果 key 存在则返回 true,否则返回 false。map.delete(key)
—— 删除指定键的值,如果在调用时 key 存在,则返回 true,否则返回 false。map.clear()
—— 清空 map。map.size
—— 返回当前元素个数。map.keys()
—— 遍历并返回一个包含所有键的可迭代对象。map.values()
—— 遍历并返回一个包含所有值的可迭代对象。map.entries()
—— 遍历并返回一个包含所有实体[key, value]
的可迭代对象,map
应用for..of
时 在默认情况下使用的就是这个。map.forEach()
—— 迭代map
Set
Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值(无论是原始值还是对象引用)只能出现一次。可以按照插入顺序迭代集合中的元素。
Set的方法和属性
new Set([iterable])
—— 如果传入一个可迭代对象(如数组[1, 2, 3, 4, 5]
),它的所有元素将不重复地被添加到新的 Set 中。如果不指定此参数或其值为null
,则新的 Set 为空。set.add(value)
—— 添加一个值,返回 set 本身set.delete(value)
—— 删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 false。set.has(value)
—— 如果 value 在 set 中,返回 true,否则返回 false。set.clear()
—— 清空 set。set.size
—— 返回元素个数。set.keys()
—— 遍历并返回一个包含所有值的可迭代对象。set.values()
—— 与set.keys()
作用相同,这是为了兼容 Map。set.entries()
—— 遍历并返回一个包含所有的实体[value, value]
的可迭代对象,它的存在也是为了兼容 Map。set.forEach((value,value,set)=>{})
—— 迭代set(注意:回调函数的前两个入参是同一个值,也是为了兼容 Map)
WeakMap
info
通常,当对象、数组之类的数据结构在内存中时,它们的子元素,如对象的属性、数组的元素都被认为是可达的。例如:
如果把一个对象放入到数组中,那么只要这个数组存在,那么这个对象也就存在,即使没有其他对该对象的引用。
如果我们使用对象作为常规 Map 的键,那么当 Map 存在时,该对象也将存在。它会占用内存,并且不会被(垃圾回收机制)回收。
WeakMap的方法
tip
WeakMap 的键必须是对象,不能是原始值。
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // 正常工作(以对象作为键)
// 不能使用字符串作为键
weakMap.set("test", "Whoops"); // TypeError: Invalid value used as weak map key,因为 "test" 不是一个对象
WeakMap 只有以下的方法:
- weakMap.get(key)
- weakMap.set(key, value)
- weakMap.delete(key)
- weakMap.has(key)
WeakMap 不支持迭代以及 keys(),values() 和 entries() 方法。所以没有办法获取 WeakMap 的所有键或值。
WeakMap与垃圾回收
- WeakMap 不会阻止垃圾回收机制对作为键的对象(key object)的回收。如果在 WeakMap 中使用一个对象作为键,并且没有其他对这个对象的引用,则该对象将会被从内存中自动清除。
info
如果一个对象丢失了其它所有引用,那么它就会被垃圾回收机制自动回收。但是不能准确知道 何时会被回收。这些都是由 JavaScript 引擎决定的。JavaScript 引擎可能会选择立即执行内存清理,如果现在正在发生很多删除操作,那么 JavaScript 引擎可能就会选择等一等,稍后再进行内存清理。
WeakMap的应用场景
- WeakMap 的主要应用场景是 额外数据的存储。
- WeakMap 的另一个应用场景是缓存,存储(“缓存”)函数的结果,以便将来对同一个对象的调用可以重用这个结果。
WeakSet
只能向 WeakSet 添加对象(而不能是原始值)。
对象只有在其它某个(些)地方能被访问的时候,才能留在 WeakSet 中。
WeakSet 支持 add,has 和 delete 方法,但不支持 size 和 keys(),并且不可迭代。