歡迎您光臨本站 註冊首頁

ES5 模擬 ES6 的 Symbol 實現私有成員功能示例

←手機掃碼閱讀     kyec555 @ 2020-05-11 , reply:0

本文例項講述了ES5 模擬 ES6 的 Symbol 實現私有成員功能。分享給大家供大家參考,具體如下:
ES6 中有類語法,定義類變得簡單了
class Person { constructor(name) { this._name = name; } get name() { return this._name; } }
然而,並沒有提供私有屬性。比如上面的 Person 其實是希望在構造的時候傳入 name ,之後不允許修改了。不過,由於沒有私有屬性,所以難免有人會這樣幹:
Person james = new Person("James"); james._name = "Tom"; // God Save Me
不過,如果想定義私有成員,也有變通的方式,比如廣為留傳的 Symbol 大法
var Person = (function() { let _name = Symbol(); class Person { constructor(name) { this[_name] = name; } get name() { return this[_name]; } } return Person; })();
其實質在於匿名函式中的 Symbol 例項 _name 是區域性變數,在外部不可訪問。而 Symbol 由於自身的唯一性特點,也沒法再造一個相同的出來,所以就模擬出來一個私有成員了。
按照此思路,在 ES5 中其實也很容易模擬私有成員。區域性變數是很容易做到的,在函式範圍內 let 和 var 是一樣的效果。問題在於模擬 Symbol 的唯一性。
ES5 沒有 Sybmol,屬性名稱只可能是一個字串,如果我們能做到這個字串不可預料,那麼就基本達到目標。要達到不可預期,一個隨機數基本上就解決了。
var Person = (function() { var _name = "00" + Math.random(); function Person(name) { this[_name] = name; } Object.defineProperty(Person.prototype, "name", { get: function() { return this[_name]; } }); return Person; })();
如果這個程式在 Web 頁面中載入,那麼每次重新整理頁面 _name 的值都會不同,但並不會影響程式的邏輯,外部程式不會出現任何不適。
然而與 Symbol 方案相比,它的問題在於這個 _name 的值不會像 Symbol 一樣會隱藏起來,在控制檯可以用很多種辦法把它找出來――當然在除錯階段這樣做也沒什麼不可以。在開發階段這個值仍然是不可預料的。
對於單個私有屬性的情況,有人會找到私有 Key 的規律,比如上面的私有 Key 就是以 "000." 開始的,遍歷物件屬性很容易找出來。在多個私有 Key 的情況下,也可以透過一些技術手段來找,比如
function getPersonNameKey() { var v = "" + Math.random(); var p = new Person(v); for (var k in p) { if (p[k] === v) { return k; } } }
但這些都是後話,做起來太費勁,一般人不會這麼幹。何況 Symbol 也是可以遍歷的(透過 Object.getOwnPropertySymbols() ),完全可以以同樣的方法來獲取私有 Key。
綜上,ES5 中模擬 Symbol 來實現私有屬性的目的已經達到了。


[kyec555 ] ES5 模擬 ES6 的 Symbol 實現私有成員功能示例已經有430次圍觀

http://coctec.com/docs/javascript/show-post-233800.html