這篇文章讓你徹底搞懂ES6中的Class(全面解析)

馮智豪發表於2020-01-20

前言

提到ES6中的class你會想到什麼呢?可能有的小夥伴只是知道它,或許用過一兩次,沒關係,這次我們從頭開始,帶你體驗class的鐵漢柔情(強大和優雅);

跟往常一樣,我們需要帶著三個問題去看這篇文章:what?how? where?


什麼是Class

使用react的小夥伴都知道,最初學習使用react框架的時候,首先了解的就是通過class來書寫元件,所以,通過閱讀這篇文章,也是為學習react打一個重要的基礎!讓我們先看一個class標準的寫法吧:

   class Point {
       constructor (x, y) {
           this.x = x
           this.y = y
       }
       MyName () {
           return (`我的名字叫${this.x}${this.y}!`)
       }
   } 
   let getName = new Point('f', 'zh');
   getName.MyName()   // 我的名字叫fzh
複製程式碼

通過上面的程式碼可以看出這個class的寫法,與ES5中建構函式的寫法很相似,沒錯,class就是建構函式的語法糖(可以理解成class就是建構函式的另一種寫法),使用的時候,也是直接對class(類)使用new命令,跟建構函式的用法完全一致;考慮到有的同學不太明白上面寫的啥,在這裡解釋一下:

  1. 首先宣告瞭一個名字為Point的class,換做ES5的寫法就是 function Point ( ) { }
  2. class裡面寫的方法,最終都定義在了 class 的原型上,換做ES5的寫法就是:Point.prototype.MyName = function ( ) { }
  3. constructor 方法就是構造方法,裡面的 this 代表例項物件,constructor 屬性,直接指向“類”的本身;
  4. constructor 是class的預設方法,通過 new 命令生成物件例項時,自動呼叫 constructor ,即使沒有定義 constructor ,也會預設有一個空的 constructor

它的絕大部分功能,ES5都可以做到,新的class寫法只是讓物件原型的寫法更加清晰、更像物件導向程式設計的語法而已,光說無用,讓我們來證明一下吧:

  // 接上面程式碼
  console.log(typeof Point);   // "function"
  console.log(Point === Point.prototype.constructor);   // true
複製程式碼

這段程式碼表明瞭類的資料型別就是函式,類的本身就是指向建構函式;

本段需要注意的地方如下:

  • class內部定義的方法都是不可列舉的;
  • 生成類的寫法需使用 new 命令,否則會報錯;
  • constructor 方法預設返回例項物件(即 this );
  • 類和模組的內部,預設就是嚴格模式,所以不需要使用 use strict 指定執行模式;
  • 類不存在變數提升;
  • 類的方法內部如果含有this,它預設指向類的例項;

以上就是class的基本知識,如果理解了上面的內容,那麼恭喜你,可以放心的在你程式碼中使用class了!

這篇文章讓你徹底搞懂ES6中的Class(全面解析)


class進階知識

開頭我們們說到過class是強大和優雅的,那麼它到底強大在哪?又優雅在哪呢?我怎麼讀現在還沒有看出來呢?好,讓我們帶著這兩個疑問去下面的文章尋找答案!

class靜態方法

類相當於例項的原型,所有在類中定義的方法都會被例項繼承,如果不想讓你定義的方法被例項繼承,也很簡單,只需要在方法前面加上 static 關鍵字,就表示該方法不會被例項繼承,而且直接通過類就可以呼叫,這也稱為 靜態方法 ,看下面程式碼:

 class MyStatic {
     static classMsg () {
         return ("My name is feng zhihao");
     }
 }
 
 // 因為"classMsg"定義方法名稱之前加了 'static' 關鍵字
 // 所以該方法是一個靜態方法
 Mystatic.classMsg();  // "My name is feng zhihao"
 
 let foo = new Mystaic();
 foo.classMsg(); // TypeError: foo.classMsg is not a function
複製程式碼

上面程式碼表明:靜態方法可以直接在類上呼叫,而不是在類的例項上呼叫,如果在例項上呼叫的話,就會丟擲錯誤,表示不存在該方法;擴充套件一下,父類的靜態方法可以被子類繼承:

class Fzh {
    static classMsg () {
        return (`新春快樂,鼠你最棒`);
    }
}

class Ibas extends Fzh {}

Ibas.classMsg();  // "新春快樂,鼠你最棒"`
複製程式碼

new.target屬性

new 是從建構函式生成例項的命令,ES6為 new 命令引入了 new.target 屬性,如果建構函式不是通過 new 命令呼叫的,那麼 new.target 會返回 undefined,在 class 內部呼叫 new.target ,返回是當前class,需要注意的是:子類繼承父類時,new.target 會返回子類:

 // " 返回當前class "
 class Register {
     constructor (x) {
         console.log(new.target === Register);
         this.x = x;
     }
 }
 
 // 返回的是true,說明new.target返回的是當前的class
 let RegClass = new Register("hello")  // true
複製程式碼
// "父類呼叫new.target返回子類"

class Register {
    constructor () {
        console.log(new.target === Register);
    }
}

class Square extends Register {
    constructor (x) {
        super(x, x);
    }
}

let sole = new Square(1);    // false(new.target返回的是子類)

複製程式碼

super關鍵字

讀到這,是不是覺得初學react的時候就是在學習class呢,尤其是 extendssuper關鍵字,我們會經常碰到它們的身影,其實super這個關鍵字既可以當做函式使用,也可以當做物件使用,在這兩種情況下,它的作用完全不同:

第一種情況: 做為函式時,super只能用在子類的建構函式中,用在其他地方會報錯;當呼叫super時,它代表父類的建構函式 ( 這是規定 ) ,ES6還規定了子類的建構函式必須執行一次super函式;

接下來的說法可能比較繞,建議讀完一遍然後看一遍程式碼,再回過頭讀一遍效果會更好:super雖然代表父類,但是它返回的是子類的例項,也就是說super內部的this是指向子類的,證明一下:

class Supe {
    constructor () {
        console.log(new.target.name);
    }
}

class SonSupe extends Supe {
    constructor () {
        super();
    }
}

new Supe();   // Supe
new SonSupe();  // SonSupe
複製程式碼

從上面程式碼可以看出,new.target指的是當前正在執行的函式,在 super 執行時,它指向的是子類 SonSuper 的建構函式,而不是父類 Supe 的建構函式,也就是說,super() 內部的this是指向子類的。

第二種情況: super作為物件時,在普通方法中指向父類的原型物件,在靜態方法中指向父類,由於 super 指向的是父類的原型物件,所以定義在父類例項上的方法或屬性是無法通過 super 呼叫的:

class A {
    gain () {
        return ("歡迎大佬指出不足,我絕對不會改~");
    }
}

class B extends A {
    constructor () {
        super();
        console.log(super.gain());   // "歡迎大佬指出不足,我絕對不會改~"
    }
}

複製程式碼

從上面程式碼可以看出super指向父類的prototype ,所以 super.gain() 等同於 A.prototype.gain() ,ES6規定:通過 super 呼叫父類方法時,super 會繫結子類的 this


結尾

這篇文章主要講了ES6中 class 的語法和小細節,我們需要做的就是記住這些知識點,真真正正的去理解它們,不斷的練習與嘗試,日後才能靈活的去運用到開發中,另外,推薦大家去看一下阮一峰出版的《ES6標準入門》這本書,最後祝小夥伴們新春快樂,永無Bug! 哦了,散會!

本人微信:

這篇文章讓你徹底搞懂ES6中的Class(全面解析)

相關文章