Set和Map数据结构
- Set
- WeakSet
- Map
- WeakMap
首先 这四个对象都是 数据结构. 用于存放数据
Set 类似数组. 但是不能重复. 如果你有重复数据,会自动忽略
属性
- size 返回长度
- add 添加
- clear 全部清除
- delete 删除其中一个
- has 确认是否存在
支持 forEach 遍历,但是不支持其他数组的遍历方式.
支持 Iterator
用途,书中介绍了两种
- 除去重复数据.
- 实现交集,并集。
实现这两种比较方便.
new Set(...[1,1,1,1,1])
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
Map
Map 可以看做约等于 new Object()
只能说他可以使用 任何对象当做 key
而 Object 只能用 string
其他的原理和 {} 一样.
不过属性有些变化
- size
- set(key,value)
- get(key)
- has(key)
- delete(key)
- clear()
遍历
iterator & forEach
他提供了完整的方式. 所以能用 Map 就用
let map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// 等同于使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
[...map.keys()]
// [1, 2, 3]
[...map.values()]
// ['one', 'two', 'three']
[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
至于 WeakSet & WeakMap
大致与 Set & Map 一致
但是参数只接受 对象 , 且不能遍历.
WeakSet不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档移除时,会引发内存泄漏。
WeakSet 其实都不适合存 DOM 元素. 因为只有一个值. 并没有什么意义.
const foos = new WeakSet()
class Foo {
constructor() {
foos.add(this)
}
method () {
if (!foos.has(this)) {
throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
}
}
}
这是书中的一个例子.
但是我并没有明白. 因为如果 Foo 的实力已经被回收. 自然也访问不了 method 方法了
至于 WeakMap 就比较适合保存 Dom
Dom元素作为 Key. value 保存一些信息.
Dom元素被移除,也不用担心内存.
let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
dec() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
let c = new Countdown(2, () => console.log('DONE'));
c.dec()
c.dec()
// DONE
还可以保证一些私有的属性.
一旦 Countdown 被删除,属性也随之消失.
我现在这一章并没有学到 Class
这种写法是否可以被另一种 class 原生的私有写法所替代
thx.