ES6 class 靜態(tài)屬性和私有方法

??ES6中新增了class的定義方法,可以說是對JavaScript這門語言的極大豐富荣茫。雖然其本質(zhì)上還是對象飘蚯,但是對于語言的使用將變得更加明確。在以往的開發(fā)中使用function來定義一個類兴泥,而現(xiàn)在,直接用class來聲明虾宇,將和其他語言沒有太大差別搓彻。

靜態(tài)方法
class MyClass {
    constructor() {}
    set(key, value) {}
    get(key) {}
}
//靜態(tài)方法

而且,在ES6中新增了static關(guān)鍵字來修飾靜態(tài)方法嘱朽,例如:

class MyClass {
    constructor() {}
    set(key, value) {}
    get(key) {}
    static say(words) {
        alert(words)
    }
}

靜態(tài)方法將不在實例化對象的方法中旭贬,因此里面不能有this,使用的時候必須直接MyClass.say()搪泳,實例化對象不擁有這個方法稀轨。靜態(tài)方法將被共享,因此所用內(nèi)存減少岸军。

實際上奋刽,由于JavaScript的語言特性,static關(guān)鍵詞修飾的方法相當于:

class MyClass {}
MyClass.say = function() {}
而正是由于這種特性艰赞,致使靜態(tài)屬性可以被動態(tài)修改佣谐,比如:

class MyClass {
  static say() {
    alert("yes")
  }
}
MyClass.say = function() {
  alert("no") 
}

但是其他語言中的private關(guān)鍵字卻沒有被ES6實現(xiàn),因此方妖,我們只能通過其他方式來實現(xiàn)它(雖然將來也是有可能實現(xiàn)的)台谍。

靜態(tài)屬性

ES6中的static只能修飾class的方法,而不能修飾屬性,所以在class中趁蕊,屬性只有兩種方式:

var sex = 0
class MyClass {
    constructor({name, age}) {
        this.name = name
        this.age = age
    }
    get sex() {
        return sex
    }
    set sex(value) {
        sex = value
    }
}

上面有兩種屬性的配置方式,一種是在constructor中使用.操作符仔役,另一種則是通過get, set來定義屬性掷伙。如果只有g(shù)et sex而沒有set sex,那么sex屬性是不能被修改的又兵。但是問題是任柜,這兩種方法都不是定義一個靜態(tài)屬性,靜態(tài)屬性是不需要實例化的沛厨,也就是說可以直接MyClass.sex這樣獲取宙地。目前已知可用的方式如下:

class MyClass {
    static get sex() {}
    static set sex() {}
}

也就是再get, set前面加static。這樣就可以直接使用MyClass.sex的方法獲取或動態(tài)設置其值逆皮,而無需實例化宅粥。

私有屬性

ES中還沒有對private的實現(xiàn)方式,也就是說在class中還無法使用這個關(guān)鍵字來修飾私有屬性或方法电谣。那么怎么實現(xiàn)私有屬性呢秽梅?首先,應該明確私有屬性的特征:

class內(nèi)部不同方法間可以使用剿牺,因此this要指向?qū)嵗瘜ο螅ū仨殻?br> 不能被外部訪問企垦,因此實例化對象$person.name既不能獲得值,也不能設定值(必須)
不能被繼承晒来,因此extends后子類不具備該屬性钞诡,但理論上可以重新手工添加(必須)
約定為前面有下劃線的this._name形式(備選)
網(wǎng)上有很多種實現(xiàn)形式,目前比較讓人認可的湃崩,主要是weakmap和symbol兩種:

const _name = new WeakMap()
class MyClass {
    constructor({name, age}) {
        _name.set(this, name)
    }
    say() {
        alert(_name.get(this))
    }
}

這種方法說實話荧降,并不是理想的私有屬性的方法,雖然利用weakmap可以將this作為鍵名竹习,但是形式上不好看誊抛,還是希望有this._name的解決方案。

const _counter = Symbol('counter');
const _action = Symbol('action');

class Countdown {
    constructor(counter, action) {
        this[_counter] = counter;
        this[_action] = action;
    }
    dec() {
        if (this[_counter] < 1) return;
        this[_counter]--;
        if (this[_counter] === 0) {
            this[_action]();
        }
    }
}

使用symbol的好處就是讓形式上更漂亮整陌,雖然采用的是this[_name]而非this._name拗窃,但是這理解起來已經(jīng)非常符合我們的習慣了。但是很明顯泌辫,它有缺點随夸,即我們可以通過Reflect.ownKeys()在外部獲取這些鍵名,這并不能達到“外部不能訪問”的目的震放。還有一個缺點宾毒,就是每多一個鍵名,就要在頂上新增一個const殿遂,使用起來也不夠靈活诈铛,不過從代碼明確性的角度看乙各,這樣做也有好處,就是不會忘記自己都定義過哪些私有屬性幢竹。還有就是耳峦,這種方案無法滿足“不能被繼承”的需求,子類將繼續(xù)擁有這些屬性焕毫。雖然對于其他開發(fā)者而言蹲坷,這些屬性是不可見的,但是通過Reflect.ownkeys還是可以被發(fā)現(xiàn)邑飒。

私有方法

理論上講循签,私有屬性和私有方法的區(qū)別是,私有方法是函數(shù)疙咸。因此县匠,只需要將上面的私有屬性的存儲值替換為函數(shù)即可。但是作為方法罕扎,內(nèi)部的this必須指向其實例化對象聚唐,因此還是需要在稍作加工。

var _say = new WeakMap()
class MyClass {
    constructor({name, age}) {
        this.name = name
        _say.set(this, () => {
            alert(this.name)
        })
    }
}

由于使用了箭頭函數(shù)腔召,函數(shù)體內(nèi)的this和外部的this是同一個杆查,因此不會發(fā)生this指向偏移的問題。

既然私有屬性可以使用set, get來實現(xiàn)臀蛛,為何私有方法不也用它來實現(xiàn)呢亲桦?其實,完全沒有必要這樣去做浊仆,就像在class外部加一個attributions一樣客峭,我們也可以在class外部創(chuàng)建函數(shù),這些函數(shù)只有在同一個文檔中可見抡柿,因此對外部也是私有的舔琅,外部程序無法獲取。

var factories = {
    a: function(options) { // 這里一定要用function洲劣,而不能用箭頭函數(shù)备蚓,因為使用箭頭函數(shù)將不能使用bind
        this.render()
    },
}

export default class MyClass {
    render() {}
    call(fun) {
        if(!factories[fun]) return
        return factories[fun].bind(this)
    }
    test() {
        this.call('a')('options') // 使用call來調(diào)用私有方法,第一個括號填寫函數(shù)名囱稽,第二個括號填寫該函數(shù)的參數(shù)
    }
}

如果你不想用兩個括號那么麻煩郊尝,要么不允許傳入?yún)?shù),要么可以用apply代替:

export default class MyClass {
    render() {}
    call(fun, ...args) {
        if(!factories[fun]) return
        return factories[fun].apply(this, args)
    }
    test() {
        this.call('a', options) // 使用call來調(diào)用私有方法战惊,第一個括號填寫函數(shù)名流昏,第二個括號填寫該函數(shù)的參數(shù)
    }
}

如果你還想省事,甚至可以不用把函數(shù)都包含在factories里面,直接定義函數(shù)况凉,在類里面使用apply:

function my_fun(options) {
  this.render()
}

export default class MyClass {
    render() {}
    test() {
      my_fun.apply(this, 'options')
    }
}

沒人會知道你都在類內(nèi)部使用過哪些私有方法谚鄙,雖然這些方法實際上都在操作著實例化對象。
z轉(zhuǎn)載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刁绒,一起剝皮案震驚了整個濱河市襟锐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膛锭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚊荣,死亡現(xiàn)場離奇詭異初狰,居然都是意外死亡,警方通過查閱死者的電腦和手機互例,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門奢入,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人媳叨,你說我怎么就攤上這事腥光。” “怎么了糊秆?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵武福,是天一觀的道長。 經(jīng)常有香客問我痘番,道長捉片,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任汞舱,我火速辦了婚禮伍纫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昂芜。我一直安慰自己莹规,他們只是感情好,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布泌神。 她就那樣靜靜地躺著良漱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腻扇。 梳的紋絲不亂的頭發(fā)上债热,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音幼苛,去河邊找鬼窒篱。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的墙杯。 我是一名探鬼主播配并,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼高镐!你這毒婦竟也來了溉旋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤嫉髓,失蹤者是張志新(化名)和其女友劉穎观腊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算行,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡梧油,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了州邢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片儡陨。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖量淌,靈堂內(nèi)的尸體忽然破棺而出骗村,到底是詐尸還是另有隱情,我是刑警寧澤呀枢,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布胚股,位于F島的核電站,受9級特大地震影響硫狞,放射性物質(zhì)發(fā)生泄漏信轿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一残吩、第九天 我趴在偏房一處隱蔽的房頂上張望财忽。 院中可真熱鬧,春花似錦泣侮、人聲如沸即彪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隶校。三九已至,卻和暖如春蛹锰,著一層夾襖步出監(jiān)牢的瞬間深胳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工铜犬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舞终,地道東北人轻庆。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像敛劝,于是被迫代替她去往敵國和親余爆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348