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

时间:2019-06-16 09:24:52

标签: javascript private-members

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

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

我很容易理解symbol(),但是我没有得到弱图。在这种情况下,我应该使用weakmap还是可以一直使用符号?

1 个答案:

答案 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的方法相比,它们的编写要容易得多。