WeakMap 与 Symbol 在类私有数据的应用
用 WeakMap 实现
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)();
}
}
}
WeakMap 的键名是对象的弱引用,其所对应的对象可能会被自动回收,只要不暴露 WeakMap,私有数据就是安全的。
Pros.
- 私有属性命名不会冲突
Cons.
- 代码不够优雅
用 Symbol 实现
const _counter = Symbol('counter');
const _action = Symbol('action');
class Countdown {
constructor(counter, action) {
this[_counter] = counter;
this[_action] = action;
}
dec() {
if (this[_counter] < 1) return;
this[_counter]--;
if (this[_counter] === 0) {
this[_action]();
}
}
}
每一个 Symbol 都是唯一的,这就是为什么使用 Symbol 的属性键名之间不会冲突的原因。并且,Symbol 某种程度上来说是隐式的,但也并不完全是:
let c = new Countdown(2, () => console.log('DONE'));
console.log(Object.keys(c));
// []
console.log(Reflect.ownKeys(c));
// [Symbol(counter), Symbol(action)]
Pros.
- 私有属性命名不会冲突
Cons.
- 代码不够优雅
- 不太安全,可以通过 Reflect.ownKeys() 列表一个对象所以的属性键名