JavaScript中class繼承超乎你的想象《一》

vi_young發表於2018-06-30

JavaScript中class繼承超乎你的想象《一》

引子

在前端框架中使用類(class)繼承的當屬擁有強大生態的React,我們在react中自定義一個元件往往會這樣子寫:

class MyComponent extends React.Component{
    constructor(props){
        this.state={
            user:'React',
            display:true
        }
    }
    render(){
        return(
           <div>
              <p>{this.state.user}</p>
           </div>
        )
    }
}
複製程式碼

上面就使用到了class繼承,繼承react.component的屬性和方法,在服務端,我們使用nodeJs最新的框架koa2,所有的繼承都是使用es6的class來進行繼承。那麼廢話不多說,一起來看一看它的廬山真面目。

簡介

class Parent{
   
}
class Child extends Parent{
    constructor(x,y,color){
        super(x,y);//呼叫父類的constructor(x,y)
        this.color=color;
    } 
    toString(){
        return this.color+''+super.toString();//super.toString();呼叫了父類的toString()方法
    }
}
複製程式碼

上面定義了一個Child類,該類通過extends關鍵字繼承了Parent類的所有屬性和方法,constructor方法和toString方法中都出現了super關鍵字,它在這裡表示父類的建構函式,用來新建立父類的this物件。

子類必須在constructor方法中呼叫super的方法,否則新建例項會報錯,這是因為子類沒有自己的this物件,而是繼承父類的this物件,然後對其進行加工,不呼叫super方法,子類就得不到this物件。

class Parent{
   /*........*/
}
class Child extends Parent{
    constructor(x,y,color){
      
    } 

}
let cp=new Child()//ReferenceError;
複製程式碼

上面的程式碼中,Child 雖然繼承了Parent類,但是在自己的的建構函式中沒有呼叫super方法,導致新建例項報錯。

在這裡我們就得聊一聊es5和es6的繼承實質,在es5的繼承實質是先創造子類的例項物件this,然後再將父類的方法新增到this上面,也就是Parent.apply(this)。而es6的繼承機制完全不同,實質是先創造父類的例項物件this(所以必須呼叫super方法),然後使用子類的建構函式去修改this。

注意點

1.如果子類沒有定義constructor方法,那麼這個方法會被預設新增,如下程式碼,也就是說無論有沒有顯示定義,任何一個子類都有constructor方法。

class dog extends  Aimals{
    constructor (...args){
        super(...args)
    }
}
//兩者等價
class dog extends  Aimals{
    constructor (...args){
        super(...args)
    }
}
複製程式碼

2.另一個要注意的地方是,在子類的建構函式中,只有呼叫super之後才可以使用this關鍵字,否則會報錯,這是因為子類例項的構建是基於父類例項的加工,只有super方法才能返回父類的例項。

class Animals{
   constructor (name,age)
       this.name=name;
       this.age=age;
    }  
}
class dog extends  Animals{
    constructor (name,age,color){
       this.color=color;   //ReferenceError
       super(name,age)
       this.age=age;
       this.color=color; //正確
    }
}
複製程式碼

上面的程式碼,子類的constructor方法沒有呼叫super之前就使用this關鍵字,結果報錯,而在super之後就是正確的。

相關文章