1. 約定前端
實現閉包
class Example { constructor() { this._private = 'private'; } getName() { return this._private } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); // private
優勢函數
缺點性能
2. 閉包學習
實現一優化
/** * 實現一 */ class Example { constructor() { var _private = ''; _private = 'private'; this.getName = function() {return _private} } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); // undefined
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提高思惟能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。this
優勢編碼
缺點調試
實現二code
/** * 實現二 */ const Example = (function() { var _private = ''; class Example { constructor() { _private = 'private'; } getName() { return _private; } } return Example; })(); var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); // undefined
優勢
缺點
3. Symbol
實現
const Example = (function() { var _private = Symbol('private'); class Example { constructor() { this[_private] = 'private'; } getName() { return this[_private]; } } return Example; })(); var ex = new Example(); console.log(ex.getName()); // private console.log(ex.name); // undefined
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提高思惟能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。
優勢
缺點
4. WeakMap
實現
/** * 實現一 */ const _private = new WeakMap(); class Example { constructor() { _private.set(this, 'private'); } getName() { return _private.get(this); } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex.name); // undefined
若是這樣寫,你可能以爲封裝性不夠,你也能夠這樣寫:
/** * 實現二 */ const Example = (function() { var _private = new WeakMap(); // 私有成員存儲容器 class Example { constructor() { _private.set(this, 'private'); } getName() { return _private.get(this); } } return Example; })(); var ex = new Example(); console.log(ex.getName()); // private console.log(ex.name); // undefined
優勢
缺點
5. 最新提案
class Point { #x; #y; constructor(x, y) { this.#x = x; this.#y = y; } equals(point) { return this.#x === point.#x && this.#y === point.#y; } }
那麼爲何不直接使用 private 字段呢?好比說這樣:
class Foo { private value; equals(foo) { return this.value === foo.value; } }
簡單點來講,就是嫌麻煩,固然也有性能上的考慮……
舉個例子,若是咱們不使用 #,而是使用 private 關鍵字:
class Foo { private value = '1'; equals(foo) { return this.value === foo.value; } } var foo1 = new Foo(); var foo2 = new Foo(); console.log(foo1.equals(foo2));
在這裏咱們新建了兩個實例,而後將 foo2 做爲參數傳入了 foo1 的實例方法中。
那麼咱們能夠獲取 foo2.value 的值嗎?若是咱們直接 foo2.value
確定是獲取不到值的,畢竟是私有變量,但是 equals 是 Foo 的一個類方法,那麼能夠獲取到的嗎?
答案是能夠的。
其實這點在其餘語言,好比說 Java 和 C++ 中也是同樣的,類的成員函數中能夠訪問同類型實例的私有變量,這是由於私有是爲了實現「對外」的信息隱藏,在類本身內部,沒有必要禁止私有變量的訪問,你也能夠理解爲私有變量的限制是以類爲單位,而不是以對象爲單位,此外這樣作也能夠爲使用者帶來便利。
既然獲取值是能夠的,那麼打印的結果應該爲 true,可是若是咱們傳入的值不是 Foo 的實例,而是一個其餘對象呢?
var foo1 = new Foo(); console.log(foo1.equals({ value: 2 }));
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提高思惟能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。
固然這裏代碼也是能夠正常運行的,可是對於編譯器來講,就有一點麻煩了,由於編譯器不知道 value 究竟是 foo 的正常屬性仍是私有屬性,因此編譯器須要作判斷,先判斷 foo 是否是 Foo 的實例,而後再接着獲取值。
這也意味着每次屬性訪問都須要作這樣一個判斷,而引擎已經圍繞屬性訪問作了高度優化,懶得改,並且還下降速度。
不過除了這個工做以外,還會有一些其餘的內容須要考慮,好比說:
關於使用 # 而不使用 private 更多的討論能夠參考這個Issue。
固然這些問題均可以被解決啦,就是麻煩了點。
而若是你選擇 #,實現的方式將跟 JavaScript 對象屬性徹底沒有關係,將會使用 private slots 的方式以及使用一個新的 slot 查找語法,總之就是會比 private 的實現方式簡單不少。