JavaScript從某些角度來(lái)看是一門殘缺的語(yǔ)言,即使es6在語(yǔ)法層面上實(shí)現(xiàn)了類和繼承,但也只不過(guò)是語(yǔ)法糖而已,而且還沒有實(shí)現(xiàn)私有成員。
當(dāng)然,JavaScript沒有什么不能靠hack來(lái)實(shí)現(xiàn)的,下面介(摘)紹(抄)一下幾種模擬出私有成員的方法。
基于約定
如果使用ES6,約定以下劃線_
開頭的成員名作為私有成員。
class Animal {
constructor() {
this._notPublicProperty = 2
}
_notPublicMethod () {
return this._notPublicProperty
}
}
這樣貌似也勉強(qiáng)夠用,但是只能靠使用者的自覺,遵守命名規(guī)則。
ES5基于閉包
function Animal() {
}
Animal.prototype = (function () {
var self = this;
var _notPublicProperty = 2;
function _notPublicMethod() {
return _notPublicProperty;
}
return {
constructor: Animal,
getNotPublicProperty: function() {
return _notPublicMethod.call(this)
}
}
}())
var dog = new Animal()
console.log(dog.getNotPublicProperty()); // 2
console.log(dog._notPublicMethod()); // ReferenceError: _notPublicProperty is not defined
Symbol
復(fù)習(xí)一下JavaScript的六種基本數(shù)據(jù)類型
undefined null number string object boolean
ES6為JavaScript引入了一種新的基本數(shù)據(jù)類型 -- Symbol
。
Symbol是一個(gè)全局函數(shù),每調(diào)用一次就會(huì)產(chǎn)生一個(gè)唯一的字符串,關(guān)于Symbol的詳細(xì)介紹可以參見 阮一峰的ES6教程
const _notPublicMethod = Symbol()
const _notPublicProperty = Symbol()
class Animal {
constructor() {
this[_notPublicProperty] = 2;
}
[_notPublicMethod]() {
return this[_notPublicProperty]; // 必須用中括號(hào)
}
getNotPublicProperty() {
return this[_notPublicMethod]()
}
}
var dog = new Animal()
console.log(dog.getNotPublicProperty()); // 2
console.log(dog._notPublicMethod()); // ReferenceError: _notPublicProperty is not defined
每次都要?jiǎng)?chuàng)建一個(gè)Symbol還是不那么完美,但是已經(jīng)不錯(cuò)了。
WeakMap
Map和WeakMap都是ES6新引入的數(shù)據(jù)結(jié)構(gòu)。
Map和Object類似,都是hash結(jié)構(gòu)。Object的鍵只能是字符串,而Map打破了這一限制,鍵可以是任意數(shù)據(jù)類型,而WeakMap比Map要弱一點(diǎn),鍵只能是對(duì)象;且WeakMap的鍵名所指向的對(duì)象,不計(jì)入垃圾回收機(jī)制。
主要的思路是,在類的級(jí)別上創(chuàng)建一個(gè) WeakMap 容器,用于存儲(chǔ)各個(gè)實(shí)例的私有成員
const store = new WeakMap()
class Animal {
constructor() {
var self = this;
function _notPublicMethod() {
return store.get(this)._notPublicProperty
}
store.set(this,{
_notPublicProperty: 2,
_notPublicMethod: _notPublicMethod.bind(self)
})
}
getNotPublicProperty() {
return store.get(this)._notPublicMethod
}
}
var dog = new Animal()
console.log(dog.getNotPublicProperty()); // 2
console.log(dog._notPublicMethod()); // ReferenceError: _notPublicProperty is not defined
貌似引入WeakMap使得問(wèn)題更加復(fù)雜,還是我的打開方式不對(duì)?
最后,還是希望babel和node能夠盡快支持最新的提案,使用#
來(lái)自然的標(biāo)識(shí)私有成員,寫hack真的很hack啊!