這篇文章帶給大家的內容是關於ES6中私有變數的實作總結(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
在閱讀 《ECMAScript 6 入門》的時候,零散的看到有私有變數的實現,所以在此總結一篇。
class Example { constructor() { this._private = 'private'; } getName() { return this._private } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); // private
#寫法簡單
調試方便
相容性好
外部可以存取和修改
語言沒有配合的機制,如for in 語句會將所有屬性枚舉出來
命名衝突
/** * 实现一 */ 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
#無命名衝突
/** * 实现二 */ 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
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
/** * 实现一 */ 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; } }
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
}));
當然這裡程式碼也是可以正常運作的,但是對於編譯器來說,就有一點麻煩了,因為編譯器不知道value 到底是foo 的正常屬性還是私有屬性,所以編譯器需要做判斷,先判斷foo 是不是Foo 的實例,然後再接著取得值。
這也意味著每次屬性存取都需要做這樣一個判斷,而引擎已經圍繞屬性存取做了高度優化,懶得改,而且還降低速度。
不過除了這個工作之外,還會有一些其他的內容需要考慮,比如說:
你必須將私有的key 編碼進每個詞法環境
for in 可以遍歷這些屬性嗎?
私有屬性和正常屬性同名的時候,誰會封鎖誰?
怎麼防止私有屬性的名稱不被偵測出來。
關於使用 # 而不使用 private 更多的討論可以參考這個 Issue。
而如果你選擇#,實作的方式將跟JavaScript 物件屬性完全沒有關係,將會使用
private slots的方式以及使用一個新的slot 尋找語法,總之就是會比private 的實作方式簡單很多。
#
以上是ES6中私有變數的實作總結(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!