es6 繼承

1. 關於class的本質

定義一個類

class Person{
    constructor(skin,language){
        this.skin=skin;
        this.language=language;
    }
    say(){
        console.log('I am a Person')
    }
}

由於class本質還是一個function,因此它就會擁有一個的prototype屬性,當new一個class時,會把class的porototype屬性賦值給這個新對象的 __proto__屬性。(prototype是函數的一個屬性,它是一個指針。對於構造函數來說,prototype是作爲構造函數的屬性。prototype也可以是一個對象,prototype是對象實例的原型對象。所以prototype即是屬性,又是對象。好繞啊~~~~
在new一個對象時,可以理解爲一個對象沒有ptototype屬性,所以把ptototype給一個對象的 __proto__。

console.log(typeof Person);//function
var p = new Person('unkown','unknown');
console.log(p);//Person {skin: "unkown", language: "unknown"}
console.log( __proto__==Person.prototype);//ture

new一個對象時,會經歷以下幾個步驟(摘自javascript高級程序設計):
(1)創建一個對象;
(2)將構造函數的作用域賦值給新對象(因此this就指向了這個新對象);
(3)執行構造函數中的代碼(爲這個新對象添加屬性);
(4)返回新對象
由此可見console.log(p)的結果。

2.constructor方法

constructor 方法是默認的方法,在new一個對象時,自動調用該方法。在一個類中必須有一個constructor,如果沒有定義,則會默認添加一個。

constructor() {}

3.class的繼承

和其他面嚮對象語言一樣,class用extends實現繼承。
1)子類沒constructor時

class American extends Person{
    aboutMe(){
        console.log(this.skin+' '+this.language)
    }
}

子類American繼承父類Person,子類沒用定義constrcutor,則默認添加一個,並且在constrcutor中調用super函數,相當於調用父類的構造函數。調用super函數是爲了在子類中獲得父類的this,調用之後this指向子類。也就是父類.prototype.constructor.call(this)。

class Chinese extends Person{
    constructor(skin,language,positon){
        //console.log(this);//報錯
        super(skin,language);
        //super();
        //console.log(this);調用super後得到了this,不報錯
        this.positon=positon;
    }
    aboutMe(){
        console.log(this.skin+' '+this.language+' '+this.positon);
    }
}

2)子類有constructor
子類必須在constructor方法中調用super方法,否則new實例時會報錯。因爲子類沒有自己的this對象,而是繼承父類的this對象。如果不調用super函數,子類就得不到this對象。super()作爲父類的構造函數,只能出現在子類的constructor()中;但是super指向父類的原型對象,可以調用父類的屬性和方法。

class Chinese extends Person{
    constructor(skin,language,positon){
        //console.log(this);//在沒有調用super之前輸出this會報錯
        super(skin,language);
        //super();//不給父類構造函數傳參,父類的構造數的值爲undefined
        console.log(this);
        this.positon=positon;
    }
    aboutMe(){
        console.log(this.x+' '+this.y+' '+this.positon);
    }
}

4.實例化子類對象

實例化子類對象時,子類對象可以擁有父類的屬性和方法,子類對象還可以擁有自己的屬性和方法。比如chinese 繼承了父類的say方法,還擁有自己的chinese say方法。最後兩行代碼表示
1)子類的__proto__屬性,表示構造函數的繼承,總是指向父類。

2)子類的prototype屬性的__proto__屬性表示方法的繼承,總是指向父類的prototype屬性-----摘自阮一峯老師的ES6入門

var american = new American('white','English');
var chinese =new Chinese('yellow','chinese','changsha');
chinese.say();//I am a Person
chinese.chinesesay();//I am a Person   I am a Chinese
console.log(American.__proto__===Person);//true 
console.log(American.__proto__);//父類對象
console.log(American.prototype.__proto__===Person.prototype);//true

 

ES6 class的繼承使用細節

2017年04月28日 17:43:00

閱讀數:3881

ES6 class的繼承與java的繼承大同小異,如果學過java的話應該很容易理解,都是通過extends關鍵字繼承。


 
  1. class Animal{

  2. constructor(color){

  3. this.color = color;

  4. };

  5. }

  6. class Bear extends Animal{

  7. constructor(){

  8. super();

  9. }

  10. }

其餘的就不多說了,這裏着重講一下ES6中super關鍵字的使用。

ES6子類繼承父類,必須在constructor函數的第一行調用super();之後才能使用關鍵字this,這是因爲子類中沒有自己的this對象,而是繼承父類的this對象,然後才能爲這個this添加相應的屬性和方法。不然就會報錯,相當於Parent.apply(this);而SE5則正好和這個相反,它先創造了自己的this對象,然後才添加父類的方法屬性到這個對象裏。

super在子類中一般有三種作用

  1. 作爲父類的構造函數調用,就是上面所說的那種方法。
  2. 在普通方法中,作爲父類的實例調用
  3. 在靜態方法中,作爲父類調用

在普通方法中調用,此時指向父類的實例


 
  1. class Animal{

  2. constructor(color){

  3. this.color = color;

  4. }

  5. run(){

  6. return "run";

  7. }

  8. }

  9. class Bear extends Animal{

  10. constructor(){

  11. super();

  12. console.log(super.run());

  13. }

  14. }

在靜態方法中調用,此時指向父類


 
  1. class Animal{

  2. constructor(color){

  3. this.color = color;

  4. }

  5. run(){

  6. return "run";

  7. }

  8. static run(){

  9. return "static run"

  10. }

  11. }

  12. class Bear extends Animal{

  13. constructor(){

  14. super();

  15. console.log(super.run());//run

  16. }

  17. static go(){

  18. super.run();//static run

  19. }

  20. }


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章