javascript 私有方法中的 symbol 和 weakmap 有什么区别?

what is the difference between symbol and weakmap in javascript private methods?

我看到使用符号和弱映射在对象内创建私有成员。他们相似吗?它们都分配给对象外的 a 属性,然后在对象内被调用。

   const _length=Symbol() or const _length=new Weakmap()

我很容易理解 symbol() 但是我没有得到 weakmap。在哪种情况下我应该使用 weakmap 或者我可以一直使用 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();

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 字段提案的一部分。

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.

的方法更容易编写