熟悉面向對象編程的都知道,面向對象編程最重要的原則之一 - 從外部接口劃份內部接口。也就是說,針對某一類事物,咱們其實並非那麼在意其內部到底是怎樣去實現的,只關心怎樣使用而已。
爲了理解這點,讓咱們先來看看現實生活中的列子。一般,咱們使用的設備很是複雜。可是從外部接口界定內部接口容許使用它們沒有什麼問題。列如一輛汽車。從外面看主要有:輪子、車身、車頂、方向盤等。程序員
可是,內部...編程
有許多的細節,可是咱們並不用去知道這些細節,也能夠很好地開車車。ide
汽車很是可靠,不是嗎?咱們可使用不少年,只有在出現問題時才能使用它 - 進行維修。汽車的可靠性和使用的簡單性在於隱藏內部細節。this
若是咱們從汽車上取下發動機,那麼使用它將會複雜得多(安裝在哪?),而且危險(它能夠電擊)。spa
因此,面向對象編程就相似於汽車同樣。code
在面向對象的編程中,屬性和方法能夠分爲兩組:對象
若是咱們繼續與汽車進行類比 - 內部隱藏的部分:發動機、變速器、半軸等 - 是其內部接口。對於對象的運行,內部接口是很是有用的,其細節互相使用。例如,彈性元件鏈接到減震器。blog
可是從外面看,汽車被外層車殼保護着,因此沒有人能夠接觸到。細節隱藏且沒法訪問。咱們能夠經過外部接口使用它的功能。因此,咱們在使用一個對象的時候,並不關心它內部是怎樣工做的。繼承
在JavaScript中,有兩種類型的對象字段(屬性和方法):接口
在許多其餘語言中,還存在「受保護」字段:只能從類內部訪問和擴展它們。它們對內部接口也頗有用。它們在某種意義上比私有更普遍,由於咱們一般但願經過繼承類來獲取和訪問它們。
受保護的字段不是在JavaScript語言級別上實現的,但實際上它們很是方便,咱們也能夠模擬地去實現它們。如今咱們用JavaScript來製做一臺具備這些類型屬性的汽車。
class MBWCar{ oilAmount = 0; // the amount of oil inside constructor(power){ this.power = power alert( `Created a mbw-car, power: ${power}` ); } } // create the mbw car let mbwCar = new MBWCar(100) // oil water mbwCar.oilAmount = 200
從上面的代碼能夠看出oilAmount與power這兩個屬性是公共的,咱們能夠在外部輕易地設置以及獲取它們。
讓咱們將oilAmount屬性更改成protected以對其進行更多控制。例如,咱們不但願任何人將其設置爲零如下。
這不是在語言層面強制去執行,但我們程序員之間有一個衆所周知的慣例,即不該該從外部訪問這些屬性和方法。
class MBWCar{ _oilAmount = 0; constructor(power){ this._power = power } set oilAmount(value){ if (value < 0) throw new Error("Negative oil"); this._oilAmount = value } get oilAmount(){ return this._oilAmount } } // create the mbw car let mbwCar = new MBWCar(100) // oil water mbwCar.oilAmount = -10 //Error Negative oil
如今訪問受到控制,所以將油量設置爲零如下將失敗。
那麼咱們能夠把power屬性設置爲只讀屬性,這在一些程序開發中也有相似的須要,某些屬性只讀不可更改其值。
class MBWCar{ constructor(power){ this._power = power } get power(){ return this._power } } // create the mbw car let mbwCar = new MBWCar(100) alert(`Power is: ${mbwCar.power}W`); // Power is: 100W mbwCar.power = 25 // Error (no setter)
class Car{ _oilMount = 0; setOilMount(value){ if(value<0) throw Error('Negative oil') this._oilMount = value } getOilMount() { return this._oilMount; } } let mbw = new Car() mbw.setOilMount(100); alert(mbw.getOilMount());
受保護的屬性是能夠繼承的
若是咱們繼承類MBWCar擴展Car,那麼沒有什麼能阻止咱們重新類的方法中訪問this._oilMount 或this._power屬性。 因此受保護的屬性是能夠繼承的,不像接下來咱們所說的私有屬性。
這是JavaScript後面新增的一個針對類屬性的語法。JavaScript引擎不支持,或者部分支持,須要進行polyfilling
在JavaScript的提議中,有一個已完成的標準,爲私有屬性和方法提供語言級支持。
私有的私有字段與#開頭,僅在類的內部可進行訪問.
class Car{ #oilLiMit = 100; #checkOil(value){ if(value<0) throw Error(`Negative oil`) if (value > this.#waterLimit) throw new Error("Too much oil"); } } let car = new Car(); // can't access privates from outside of the class car.#checkOil(); // Error car.#waterLimit = 1000; // Error class BWMCar extends Car{ method() { alert( this.#oilLiMit ); // Error: can only access from Car } }
私有字段不可以經過this[name]去訪問
class User{ sayHi(){ let filedName = "Darkcod" alert(`Hello,${this.filedName}`) //Hello,undefined } } new User().sayHi()
總結: