ES6之class基本語法

類這個概念對於作後臺的應該是很是熟悉,JavaScript的類對於其餘面向對象的語言差別很大,只能使用構造函數生成實例對象。爲了接近傳統語言,ES6引入了class類這個概念,經過class關鍵字定義類。編程

Class實際上是一個語法糖,幾乎全部功能均可以用其餘方法實現,只是讓代碼更清晰,更像面向對象編程。bash

語法:函數

class User{  

  constructor(){     

   console.log('默認調用');  

  }  

  eat(){    

    console.log('eat方法');  

  }

}
var user = new User();//默認調用

user.eat()//eat方法
複製代碼

注意,類的方法是不能加function關鍵字,方法之間也不能用逗號分隔,否則會報錯。類的全部方法都定義在類的prototype方法。在類的實例調用方法就是調用原型上的方法。ui

class User{  

  eat(){}

}
複製代碼

等同於:this

function User() {}

User.prototype.eat = function () {}
複製代碼

類內部定義的方法都是不可枚舉的,這跟ES5不同。spa

Constructor方法:prototype

這個方法是默認方法,經過new生成實例對象的時候自動調用,每一個類都會有,若是沒有顯式定義,會自動添加一個空的constructor方法。默認返回實例對象,也就是this。你也能夠返回另外的對象,這跟構造函數是同樣的。類必須使用new調用,而咱們的構造函數還能當作方法直接調用。code

與 ES5 同樣,實例的屬性除非顯式定義在其自己(即定義在this對象上),不然都是定義在原型上(即定義在class上),類的全部實例共享一個原型對象,所以一個實例對象經過原型__proto__改寫了原型,全部實例對象都會改變,全部不推薦使用實例的__proto__改寫原型。cdn

一樣的,getter函數和setter函數也能夠在類裏面使用關鍵字get和set:對象

class User{  

  constructor(){    

    this.name = 'wade'; 

   }    get eat(){   

   return '這是get';  

  }  

  set eat(val){     

   console.log('set調用了');  

  }

}

var user = new User();

user.eat = 3//set調用了

console.log(user.eat);//這是get
複製代碼

表達式:

屬性能夠用[]表達式,這個跟對象是同樣的,類也能夠直接用表達式定義:

var val = 'my'

var User = class Muser{   

 [val](){     

       }

}
複製代碼

Muser只能在class內部可用,class外部使用User。若是內部不使用,也能夠省略Muser或者當即執行class:

var User = class {}

var user = new class{}()
複製代碼

要注意,class默認就是嚴格模式,並且不存在變量提高,name的屬性也是返回class關鍵字後面的類名,還能夠使用Gernerator方法。類方法內部的this默認指向類的實例,單獨拿出來使用會報錯。

類的方法前面加上static關鍵字,那麼這個方法不會被實例繼承,能夠經過類調用,這個方法叫作靜態方法:

class User{  

  static eat(){     

   console.log('eat');  

  }

}var user = new User();

console.log(user.eat());//報錯

User.eat()//eat
複製代碼

若是靜態方法包含this關鍵字,這個this指的是類,而不是實例:

class User{  

  static eat() {    

    this.say();  

  }  

  static say() {    

    console.log('hello');  

  }  

  say() {     

   console.log('world');  

  }

}

User.eat() // hello
複製代碼

靜態方法和非靜態方法還能夠重名。靜態方法是能夠被子類繼承的。

實例屬性除了定義在constructor裏面,還能直接定義在最頂層:

class User1{  

  constructor(){    

    this.name = 'wade';  

  }

}

class User2{  

  name = 'kobe';

}

console.log(new User1().name);//wade

console.log(new User2().name);//kobe
複製代碼

Class自己的屬性叫作class的靜態屬性,Class.propName,不是定義在實例對象this上的屬性。Class內部只有靜態方法沒有靜態屬性,如今只有一種寫法:

class User{};User.prop = 1;

可是有提案使用static定義:

class User{  

  static prop = 1;

};
複製代碼

從代碼組織原則和聲明來看,這樣的寫法無疑是更好的。

咱們都知道代碼封裝私有屬性和私有方法是很重要的,可是ES6的class暫時是沒有提供的。變通的解決方法好比區分命名、方法移出模塊、用symbol變量等。但都不是很好。如今有個提案,使用#來提供私有屬性:

class User{  

  #prop = 1; 

  #eat(){}

};
複製代碼

只能在內部使用,外部訪問就報錯。私有屬性也能夠設置 getter 和 setter 方法。私有屬性不限於從this引用,只要是在類的內部,實例也能夠引用私有屬性:

class User{  

  #prop = 1; 

  static eat(user){     

   console.log(user.#prop); 

  }

};

User.eat(new User());//1
複製代碼

new是從構造函數生成實例對象的命令。ES6 爲new命令引入了一個new.target屬性,該屬性通常用在構造函數之中,返回new命令做用於的那個構造函數。若是構造函數不是經過new命令或Reflect.construct()調用的,new.target會返回undefined,所以這個屬性能夠用來肯定構造函數是怎麼調用的:

function User() {  

  console.log(new.target === User);//true  

  console.log(new.target !== undefined);//true

}

var user = new User();
複製代碼

若是不是new:

function User() {  

  console.log(new.target === User);//false  

  console.log(new.target !== undefined);//false

}

User();
複製代碼

Class 內部調用new.target,返回當前 Class:

class User{  

  constructor(){    

    console.log(new.target === User)//true  

  }

}

new User();
複製代碼

子類繼承父類時,new.target會返回子類。利用這個特色,能夠寫出不能獨立使用、必須繼承後才能使用的類。

相關文章
相關標籤/搜索