面向對象之類的繼承
什么是面向對象?
面向對象是一種編程思想,js本身就是基於面向對象構建出來的,例如js中有很多內置類,像promise,可以基於new promise來創建一個實例,來管理異步編程 js的面向對象,和其他編程語言還是略微不同,js中的類和實例是基於原型和原型鏈機制來處理的,而且js中的類的重載和重寫繼承和其他語言不一樣
類的繼承、封裝、多態
- 封裝:低耦合高內聚
- 多態:重載和重寫
- 重載:方法名相同,形參個數或者類型不一樣(js中不存在重載,js中重載指的是同一個方法,根據傳參不同,實現出不同效果)
- 重寫:在類的繼承中,子類可以重寫父類的方法
- 繼承:子類繼承父類上的方法
繼承常用的四種方法
子類繼承父類中的屬性和方法(目的是讓子類的實例繼承父類中的屬性和方法)
- 原型繼承
- 讓父類中的屬性和方法在子類實例的原型鏈上
- 子類的prototype指向父類的實例new A()
- 特點:
- 不像其他語言中的繼承一樣(其他語言的繼承一般是繼承拷貝,也就是子類繼承父類,會把父類中的屬性和方法拷貝一份到子類,供子類的實例調取使用)它是把父類的原型放到子類實例的原型鏈上的,實例想調取這些方法,是基於__proto__原型鏈查找機制完成的
- 子類可以重寫父類上的方法(這樣會導致父類其他的實例也受到影響)
- 父類中私有或者共有的屬性方法都會變成子類的共有屬性和方法
//父類
function A(x) {
this.x=x
}
A.prototype.getX=function(){
console.log(this.x)
}
//子類
function B(x) {
this.y=y
}
//B的原型指向A的實例
B.prototype=new A()
B.prototype.constructor=B
B.prototype.getY = function(){
console.log(this.y)
}
let b1=new B(100)
console.log(b1.y)//100
b1.getX()//undefined
b1.getY()//100
- call繼承
- 特點
- 在子類中把父類當做普通元素執行,讓父類的this指向子類的實例
- 只能繼承父類私有的屬性和方法(因為把父類當做普通函數執行了,和其原型上的屬性和方法沒有關系)
- 父類私有的變成子類私有的
- 特點
//父類
function A(x) {
this.x=x
}
A.prototype.getX=function(){
console.log(this.x)
}
//子類
function B(y) {
A.call(this,y)
this.y=y
}
B.prototype.getY = function(){
console.log(this.y)
}
let b1=new B(100)
console.log(b1.y)
b1.getX()
b1.getY()
- 寄生組合繼承 call繼承+類似於原型鏈繼承
- 特點:父類私有和共有的分別是子類實例的私有和共有屬性方法
//寄生組合繼承
//父類
function A(x) {
this.x=x
}
A.prototype.getX=function(){
console.log(this.x)
}
//子類
function B(y) {
A.call(this,y)
this.y=y
}
//Object.create創建一個空對象,讓空對象的__proto__指向A.prototype
B.prototype=Object.create(A.prototype)
B.prototype.constructor = B
B.prototype.getY = function(){
console.log(this.y)
}
let b1=new B(100)
b1.y
b1.getX()
b1.getX()
- es6中extend繼承(extends和super)
//es6中繼承
class A {
constructor(x){
this.x=x
}
getX(){
console.log(this.x)
}
}
class B extends A {
//子類只要繼承父類,可以不寫constructor,一旦寫了就要在第一句話中協商super()
//不寫constructor 瀏覽器會自動默認創建constructor(...arg){}
constructor(y) {
//把父類當做普通方法執行,給方法傳遞參數,讓方法中的this是子類的實例
super()
this.y=y
}
getY(){
console.log(y)
}
}