【譯文&摘抄】ECMAScript 6 裏面的私有變量

原文鏈接 : Private members in ES6 classes
本文已獲得原作者Greg Reimer的授權
譯文出自 : 掘金翻譯計劃
轉自:https://juejin.im/entry/572c0b2d2e958a00667a081d?utm_source=gold-miner&utm_medium=readme&utm_campaign=github
譯者 : XRene
校對者:narcotics726, jingkecn

創建一個 ES6 的類,然後給它一個私有變量。

最基礎的方法:

class Foo {
  constructor(x) {
    this.x = x;
  }
  getX() {
    return this.x;
  }
}

但是其實,這樣定義的 x 根本不是私有的,可以通過對象隨意的進行訪問。

一個同等級但是具有一些提示效果的解決方案,就是在變量名前面加上下劃線:

class Foo {
  constructor(x) {
    this._x = x;
  }
  getX() {
    return this._x;
  }
}

但即便這樣,變量 _x 依舊不是真正的私有變量。

進一步的,我們可以將 x 設置爲不可枚舉的,更好的隱藏它:

class Foo {
  constructor(x) {
    Object.defineProperty(this, 'x', {
      value: x,
      enumerable: false,
    });
  }
  getX() {
    return this.x;
  }
}

但是,如果有人讀了源代碼,還是可以隨意訪問 x。

下面這個方法才能算真正的藏起來了 x,此時通過 new Foo().x 這種方式是無法訪問到 x 的了:

class Foo {
  constructor(x) {
    this.getX = () => x;
  }
}

但是這樣的話,每一個類的實例都會包含這個函數的副本。這樣不僅效率低,同時也與預期不符:這個變量本應在存在於原型上。

好無奈,只好放大招了:

const __ = new Map();

class Foo {
  constructor(x) {
    __.set(this, { x });
  }
  getX() {
    var { x } = __.get(this);
    return x;
  }
}

這樣方法的缺點就是可能會導致內存泄漏。

解決方案就是,換成WeakMap:

const __ = new WeakMap();

class Foo {
  constructor(x) {
    __.set(this, { x });
  }
  getX() {
    var { x } = __.get(this);
    return x;
  }
}

好了!完美。

發佈了344 篇原創文章 · 獲贊 39 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章