我看到使用符号和弱映射在对象内部创建私有成员。他们相似吗?它们都在对象外部分配了一个属性,然后在对象内部被调用。
const _length=Symbol() or const _length=new Weakmap()
我很容易理解symbol(),但是我没有得到弱图。在这种情况下,我应该使用weakmap还是可以一直使用符号?
答案 0 :(得分:1)
以下是每种技术的完整示例:
const Foo = (() => {
const _length = Symbol('_length');
return class Foo {
[_length] = 0;
get length () { return this[_length]; }
set length (value) { this[_length] = value; }
}
})();
const bar = new Foo();
console.log(bar.length);
const Foo = (() => {
const _length = new WeakMap();
return class Foo {
constructor () { _length.set(this, 0); }
get length () { return _length.get(this); }
set length (value) { _length.set(this, value); }
}
})();
const bar = new Foo();
console.log(bar.length);
但是,Symbol
方法并不是真正的私有方法,如此处所示:
const Foo = (() => {
const _length = Symbol('_length');
return class Foo {
[_length] = 0;
get length () { return this[_length]; }
set length (value) { this[_length] = value; }
}
})();
const bar = new Foo();
const _length = Object.getOwnPropertySymbols(bar)[0]; // private key exposed
console.log(bar[_length]); // private property exposed
第二种方法推荐使用WeakMap
的原因是因为它允许class Foo
的实例在程序中其他地方不再引用时被垃圾回收。
相比之下,普通的Map
将对每个实例具有强大的引用,并防止对其进行垃圾回收,从而导致程序中的内存泄漏。
现在还有第三种方法最终应运用于ECMAScript规范:private fields,它是当前阶段3的TC39类字段提案的一部分。
class Foo {
#length = 0;
get length () { return this.#length; }
set length (value) { this.#length = value; }
}
const bar = new Foo();
console.log(bar.length);
与Symbol
方法相反,它们是真正的私有属性。另外,与使用WeakMap
的方法相比,它们的编写要容易得多。