首頁  >  文章  >  web前端  >  JavaScript ES6中CLASS的使用詳解

JavaScript ES6中CLASS的使用詳解

高洛峰
高洛峰原創
2016-12-06 09:30:561661瀏覽

前言

對於javascript來說,類別是一種可選(而不是必須)的設計模式,而且在JavaScript這樣的[[Prototype]] 語言中實現類別是很蹩腳的。

這種蹩腳的感覺不只是來自文法,雖然文法是很重要的原因。 js裡面有許多語法的缺點:繁瑣雜亂的.prototype 引用、試圖調用原型鏈上層同名函數時的顯式偽多態以及不可靠、不美觀而且容易被誤解成“構造函數”的.constructor。

除此之外,類別設計其實還存在更進一步的問題。傳統以類別為導向的語言中父類別和子類別、子類別和實例之間其實是複製操作,但是在[[Prototype]] 中並沒有複製。

物件關聯程式碼和行為委託使用了[[Prototype]] 而不是將它藏起來,對比其簡潔性可以看出,類別並不適用於JavaScript。

ES6中CLASS的使用

javascript傳統做法是當產生一個物件實例,需要定義建構函數,然後透過new的方式完成。

function StdInfo(){
  this.name = "job";     
  this.age = 30;     
}
 
StdInfo.prototype.getNames = function (){
  console.log("name:"+this.name);       
}
//得到一个学员信息对象
var p = new StdInfo()

   

javacript中只有對象,沒有類別。它是基於原型的語言,原型物件是新物件的模板,它將自身的屬性共享給新物件。這樣的寫法和傳統物件導向語言差異很大,很容易讓新手感到困惑。

定義類

到了ES6添加了類,作為對象的模板。以class定義一個類別:

//定义类
class StdInfo {
  constructor(){
    this.name = "job";     
    this.age = 30;  
  }
  //定义在类中的方法不需要添加function
  getNames(){
    console.log("name:"+this.name);  
  }
}
//使用new的方式得到一个实例对象
var p = new StdInfo();

   

上面的寫法更清晰、更像物件導向程式設計的語法,看起來也更容易理解。

定義的類別只是語法糖,目的是讓我們用更簡潔明了的語法創建物件及處理相關的繼承。

//定义类
class StdInfo {
  //...
}
console.log(typeof StdInfo); //function
 
console.log(StdInfo === StdInfo.prototype.constructor); //true

   

從上面的測試中可以看出來,類別的類型就是一個函數,是一個“特殊函數”,指向的是構造函數。

函數的定義方式有函數宣告和函數表達式兩種,類別的定義方式也有兩種,分別是:類別宣告和類別表達式。

類別宣告

類別宣告是定義類別的一種方式,使用關鍵字class,後面跟上類別名稱,然後就是一對大括號。把這一類需要定義的方法放在大括號中。

//定义类,可以省略constructor
class StdInfo {
  getNames(){
    console.log("name:"+this.name);
  }
}
// -------------------------------------
//定义类,加上constructor
class StdInfo {
  //使用new定义实例对象时,自动调用这个函数,传入参数
  constructor(name,age){
    this.name = name;     
    this.age = age;  
  }
   
  getNames(){
    console.log("name:"+this.name);  
  }
}
//定义实例对象时,传入参数
var p = new StdInfo("job",30)

   

constructor是預設方法,使用new定義實例物件時,自動執行constructor函數,傳入所需的參數,執行完constructor後自動傳回實例物件。

一個類別中只能有一個constructor函數,定義多個會報錯。

constructor中的this指向新建立的實例對象,並利用this往新建立的實例物件擴充屬性。

在定義實例物件時,不需要在初始化階段做一些事,可以不用顯示的寫constructor函數。如果沒有明確定義,一個空的constructor方法會被預設添加,constructor(){}

類別表達式

類別表達式是定義類別的另一種形式,類似於函數表達式,把一個函數當作值賦給變數。可以把定義的類別賦值給一個變量,這時候變數就為類別名稱。 class關鍵字之後的類別名稱可有可無,如果存在,則只能在類別內部使用。

定義類別class後面有類別名稱:

const People = class StdInfo {
  constructor(){
    console.log(StdInfo); //可以打印出值,是一个函数
  }
}
 
new People();
new StdInfo(); //报错,StdInfo is not defined;

   

定義類別中沒有類別名稱:

const People = class {
  constructor(){
 
  }
}
 
new People();

   

立即執行的類,在類前要加上new。 p為類別的實例物件。

不存在變數提升

定義類別不存在變數提升,只能先定義類別後使用,跟函數宣告有區別的。

const p = new class {
  constructor(name,age){
    console.log(name,age);
  }
}("job",30)

   

EXTENDS繼承

使用extends關鍵字實現類別之間的繼承。這比在ES5中使用繼承要方便很多。

//-----函数声明-------
//定义前可以先使用,因为函数声明提升的缘故,调用合法。
func();
function func(){}
 
//-----定义类---------------
new StdInfo(); //报错,StdInfo is not defined
class StdInfo{}

   

使用繼承的方式,子類別就擁有了父類別的方法。

如果子類別中有constructor建構函數,則必須使用呼叫super。

//定义类父类
class Parent {
  constructor(name,age){
    this.name = name;
    this.age = age;
  }
 
  speakSometing(){
    console.log("I can speek chinese");
  }
}
//定义子类,继承父类
class Child extends Parent {
  coding(){
    console.log("coding javascript");
  }
}
 
var c = new Child();
 
//可以调用父类的方法
c.speakSometing(); // I can speek chinese

   

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

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn