在 WeakMap最大的問題是無法 shim 弱引用,較次要的問題是不大方便調試。
shim 出來的 WeakMap 主要是無法追溯實例的生命週期,而實例上的私有成員的生命週期又是依賴實例, 因此將實例層級的私有成員部分放在實例上不就好了? 實例沒了,自然其屬性也隨之摧毀。而私有儲存區域的隱藏則可以使用 Symol 來做。
此方案的提供一個 createPrivate 函數,該函數會傳回一個私有的 token 函數,對外不可見,對內透過閉包函數取得, 傳入目前實例會傳回目前實例的私有儲存區域。使用方式如下:
(function() { var $private = createPrivate(); // 私有成员 token 函数,可以传入对象参数,会作为原型链上的私有成员 function MyClass() { $private(this).privateProp = ‘privateProp' ; // 闭包内引用到privateStore, 用当前实例做 key,设置私有成员 } MyClass.prototype.getPrivateProp = function () { return $private(this).privateProp; }; })(); var my = new MyClass(); alert(my.getPrivateProp()); // ‘privateProp'; alert(my.privateProp); // 弹出 undefined,实例上并没有 privateProp 属性
程式碼中主要就是實作createPrivate 函數,大概的實作如下:
// createPrivate.js function createPrivate(prototype) { var privateStore = Symbol('privateStore'); var classToken = Symbol(‘classToken'); return function getPrivate(instance) { if (!instance.hasOwnProperty(privateStore)) { instance[privateStore] = {}; } var store = instance[classToken]; store[token] = store[token] || Object.create(prototype || {}); return store[token]; }; }
上述實作做了兩層存儲,privateStore 這層是實例上統一的私有成員存儲區域,而classToken 對應的則是繼承層次之間不同類別的私有成員定義,基底類別有基底類別的私有成員區域,子類別和基底類別的私有成員區域是不同的。
當然,只做一層的儲存也可以實現,兩層儲存只是為了調試方便,可以直接在控制台透過Symbol(‘privateStore')這個屬性來查看實例各個層次的私有部分。
以上是symbol + weakmap實作javascript私有成員方式程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!