es6中的class

前言

es6的class實際上是構造函數的語法糖,可是又有區別,下面來詳細分析下classjavascript

定義

先來看下class的定義的代碼java

class Point{
     constructor(){}
     toString(){}
   }
   var p = new Point()
   p.constructor === Point.prototype.contructor//true
   Object.keys(Point.prototype)//[]
   Object.getOwnPropertyNames(Point.prototype)//['constructor','toString']

區別

  1. 在類的實例上調用方法,就是調用類的原型上的方法,可是類內部的方法是不可枚舉的,構造函數的方法是可枚舉的(是否可被for...in遍歷,object.keys),構造函數能夠遍歷除contructor以外的方法
  2. constructor是類默認的方法,經過new生成實例時自動調用該方法,若是沒有被顯示定義,這個方法會被自動建立。
  3. 類只能經過new生成實例對象,若是像直接調用class會報錯。
  4. 類的全部實例共享一個原型對象
    p2.__proto__ === p1.__proto__;//true
    這也就意味着能夠經過實例的__proto__屬性爲class添加方法,不推薦使用,由於會影響到其餘實例
  5. class不存在變量提高,這個和繼承有關,必須保證子類在父類以後定義
  6. 類和模塊內部默認都是使用嚴格模式
  7. class能夠自定義原生數據結構(Array,String等)的子類,這是es5沒法作到的,由於es5是先新建子類的this,再將父類的屬性添加到子類上,因爲父類的內部屬性子類沒法獲取,致使沒法繼承原生的構造函數

繼承

子類必須在constructor中調用super方法,不然新建實例會報錯,由於子類沒有本身的this,而是繼承了父類的this,這和es5中的繼承不同,
由於es5中的繼承是先創造子類的實例對象this,再將父類的方法添加到this上(parent.call(this)),es6中是先繼承父類的實例對象this,而後再用子類的構造函數修改this。若是子類沒有定義constructor,那麼這個方法會被默認添加。
在子類的構造函數中,只有調用super關鍵字以後,纔可以使用this關鍵字,不然會報錯,由於子類實例的構建基於對父類實例的加工,只有super方法才能返回父類的實例。es6

prototype和__proto__
大多數瀏覽器的es5實現中,每個對象都有__proto__屬性(IE8除外),指向對應的構造函數的prototype屬性。class做爲構造函數的語法糖,同時有prototype屬性和__proto__屬性,由於存在兩條繼承鏈。瀏覽器

  1. 子類的__proto__屬性表示構造函數的繼承,老是指向父類
  2. 子類prototype屬性的__proto__屬性表示方法的繼承,老是指向父類的prototype屬性

class的靜態方法

若是在一個方法前加上static關鍵字,就表示該方法不會被實例繼承,而是直接經過類調用,成爲‘靜態方法’。
看下代碼數據結構

class Foo{
  static classMethod(){}
}
Foo.classMethod();
class Bar extends Foo(){
   static classMethod(){
       return super.classMethod()
   }
}
Bar.classMethod();

上面Foo類有靜態方法classMethod,只能經過Foo.classMethod調用,不可經過實例調用,不然會報錯,父類的靜態方法可被子類繼承。函數

class的靜態屬性

靜態屬性是指class自己的屬性,即class.propname,而不是定義在實例對象(this)上的屬性。this

class Foo{}
Foo.prop = 1;
Foo.prop //1

上面的方法能夠讀、寫Foo類的靜態屬性prop,可是es6中規定,class中只有靜態方法,沒有靜態屬性es5

new.target屬性

es6爲new命令引入了new.target屬性,返回new命令所做用的構造函數,若是構造函數不是經過new命令調用的,那麼new.target會返回undefined,所以這個屬性能夠判斷構造函數是如何被調用的prototype

相關文章
相關標籤/搜索