熟悉面向对象编程的都知道,面向对象编程最重要的原则之一 - 从外部接口划份内部接口。也就是说,针对某一类事物,咱们其实并非那么在意其内部到底是怎样去实现的,只关心怎样使用而已。
为了理解这点,让咱们先来看看现实生活中的列子。一般,咱们使用的设备很是复杂。可是从外部接口界定内部接口容许使用它们没有什么问题。列如一辆汽车。从外面看主要有:轮子、车身、车顶、方向盘等。程序员
可是,内部...编程
有许多的细节,可是咱们并不用去知道这些细节,也能够很好地开车车。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()
总结: