Set
Set 是一种类似于数组,但成员的值都是唯一的,没有重复的数据结构。数组去重:[... new Set(array)]
向 Set 加入值时不会发生类型转换,所以 5 和 "5" 是两个不同的值。Set 内部判断两个值是否相同时,使用的是类似于全等运算符( === ),不同的是 Set 结构对于两个 NaN 的判断是相等的。另外,两个对象总是不相等的。
let set1 = new Set();
let a = NaN;
let b = NaN;
set1.add(a);
set1.add(b);
set1 // { NaN }
let set2 = new Set();
set2.add({});
set2.size // 1
set2.add({});
set2.size // 2
Set 实例的属性和方法
Set 实例有以下属性:
- Set.prototype.constructor:构造函数,默认就是 Set 函数
- Set.prototype.size:返回 Set 实例的成员总数
Set 实例的方法有两种:操作方法和遍历方法
操作方法:
- add(value):添加某个值,返回 Set 结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示参数是否为 Set 的成员
- clear():清除所有成员,没有返回值
遍历方法:
Set 的遍历顺序就是插入顺序。Set 只有键值,所以 keys 和 values 方法的行为一致,entries 返回的每个数组中为两个成员相等的键值
- keys():返回键名的遍历器
- values():返回键值的遍历器
- etries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// 'red'
// 'green'
// 'blue'
for (let item of set.values()) {
console.log(item);
}
// 'red'
// 'green'
// 'blue'
for (let item of set.entries()) {
console.log(item);
}
// ['red', 'red']
// ['green', 'green']
// ['blue', 'blue']
另外,借助数组的 map 和 filter 方法可以使 Set 用处增强
let set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2)); // { 2, 4, 6 }
let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0)); // { 2, 4 }
利用 Set 可以实现并集、交集、差集
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let union = new Set([...a, ...b]); // 并集,{ 1, 2, 3, 4 }
let intersect = new Set([...a].filter(x => b.has(x))); // 交集,{ 2, 3 }
let difference = new Set([...a].filter(x => !b.has(x))); // 差集,{ 1 }
WeakSet
与 Set 结构的主要区别:
- 成员只能是对象,不能是其他类型的值
- 成员都是弱引用。如果其他对象不再引用成员中的对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象是否还存在于 WeakSet 中。
- 不可遍历成员,没有 size 属性
- 没有 clear 方法
const ws = new WeakSet();
ws.add(1) // TypeError:Invalid value used in weak set
ws.add([1]) // TypeError:Invalid value used in weak set
ws.add([[1]]) // WeakSet {[1]}
成为 WeakSet 的成员的是数组的成员,而不是数组的本身,所以数组的成员必须是对象。
WeakSet 实例的方法
- WeakSet.prototype.add(value):向 WeakSet 实例中添加成员
- WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员
- WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例中
Map
Map 构造函数可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([['name', '张三'], ['titiel', 'Author']]);
const errorMap = new Map(['name', '张三']); // TypeError
如果对同一个键多次赋值,后面的值会覆盖前面的值。
const map = new Map();
map.set(['a'], 555);
map.get(['a']); // undefined,因为两个['a']不同
const map1 = new Map();
const k1 = ['a'];
const k2 = ['a'];
map
.set(k1, 111)
.set(k2, 222);
map.get(k1); // 111
map.get(k2); // 222
Map 的键是和内存地址绑定的,只要内存地址不一样,就视为两个键。当 Map 的键是简单类型的值时,只要两个值严格相等(NaN 除外,Map 将 NaN 视为同一个键),就视为同一个键。
Map 实例的属性和方法
属性:
- size 属性:size 属性返回 Map 结构的成员数
操作方法:
- set(key, value):设置 key 对应的键值,返回整个 Map 结构,因此 set 方法可以采用链式写法。如果 key 已经有值,则会更新键值
- get(key):读取 key 对应的键值,如果找不到 key,返回 undefined
- has(key):返回一个布尔值,表示 key 是否有对应的键
- delete(key):删除某个键,返回 true 表示删除成功,返回 false 表示删除失败
- clear():清除所有成员,没有返回值
遍历方法:
- keys():遍历返回键名
- values():遍历返回键值
- entries():遍历返回所有键值对
- forEach():遍历所有成员
let map = new Map([['F', 'no'], ["T", 'yes']]);
for(let key of map.entries()) {
console.log(key);
}
// ['F', 'no']
// ['T', 'yes']
WeakMap
与 Map 的主要区别:
- 只接受对象作为键名(null 除外),不接受其他类型值作为键名
- WeakMap 的键名所指向的对象不计入垃圾回收机制
- 不可遍历成员,没有 size 属性
- 没有 clear 方法
const wm = new WeakMap();
let key = {};
let obj = { foo: 1 };
wm.set(key, obj);
obj = null;
wm.get(key); // { foo: 1 }
WeakMap 实例的方法
- get()
- set()
- has()
- delete()