簡單學ES6 - class


 

前言

隨着ES6標准的定稿,眾多的特性也趨於穩定,各大瀏覽器也在逐步實現這些特性,那么對ES6有更多的了解就無可厚非了。

准備

在學習ES6之前,我們需要有一個環境來測試ES6代碼。在這里我推薦使用node的分支io.js。

  1. 如何安裝?

    1. 下載地址:https://iojs.org/en/index.html,如果各位小伙伴不習慣英文,可以把url中的en修改為cn。
    2. 然后根據自己的操作系統版本,下載合適的安裝包(主要指Windows系統)進行安裝。
    3. 安裝過程就不一一贅述了,和一般軟件一樣。
  2. 如何驗證安裝成功?

    1. 打開cmd,然后輸入iojs -v,如果輸出一個版本號,那么就代表io.js安裝成功。(PS:我現在使用的是v1.2.0)
    2. 也可以輸入iojs -p process.versions.v8查看iojs所使用的V8(PS:不是V8發動機)的版本。(PS:我這兒顯示4.1.0.14)

小窺ES6

在測試ES6代碼前,我們可以先看下io.js對ES6的支持:https://iojs.org/cn/es6.html

接下來,開始我們的ES6-Class之旅:

1、class 基礎

大家應該知道,在大部分面向對象的語言中,都有class的說法,那么在早期的Js中,面向對象的實現比較特殊,我們必須要用function來模擬。如:

//ES5及以下
function Point(x, y){
  this.x = x;
  this.y = y;
}
var p1 = new Point(100, 100);

然而在ES6中,我們可以直接使用class關鍵字,如:

//ES6
'use strict' //不能去掉,要不然iojs會提示不認識class。
class Point{
  constructor(x, y){
    this.x = x;
    this.y = y;
  }
}
var p1 = new Point(100, 100);
console.log(p1);

將以上代碼保存為1.js,那么執行如下命令:iojs --es_staging 1.js 就可以看到"{x:100, y: 100}"這個結果了。(PS:注意要在1.js的目錄打開cmd)。

接下來,看一個復雜點的,繼承:

//ES6
'use strict'
class Point{
  constructor(x, y){
    this.x = x;
    this.y = y;
  }
}
var p1 = new Point(100, 100);
console.log(p1);

class ColorPoint extends Point{
  constructor(x, y, color){
    super(x, y);
    this.color = color;
  }
}
var cp = new ColorPoint(50, 50, 'red');
console.log(cp);

//輸出繼承關系
console.log(cp instanceof ColorPoint); //true
console.log(cp instanceof Point);  //true

可以看到,和大部分語言的繼承都很類似,如果你有其他面向對象語言的基礎,那么很容易就能理解。

對Point和ColorPoint進行typeof,結果很明顯也能看到是function。

console.log(typeof Point);  // function
console.log(typeof ColorPoint);  // function

那如果對class進行函數調用呢?

Point(100, 100); //Error

如上,必須通過new調用class,直接使用函數調用則會報錯。

再來對比以下代碼:

//標准的函數可以先寫調用語句,后寫申明語句。因為會定義前置
foo();
function foo(){}
//如果是class呢?
new Foo(); //Error,Foo is not defined
class Foo{}

如上,如果是定義的class,那么必須要定義語句在前,調用在后。

再來看以下的情形:

function funThatUseBar(){
  new Bar();
}
//funThatUseBar(); //Error,Bar is not defined
class Bar{}
funThatUseBar(); //ok

如上,如果先使用了Bar,那么也是會報錯的。必須要優先定義class。

附上以上所有的js,會報錯的語句,進行了注釋。

//ES6
'use strict'
class Point{
  constructor(x, y){
    this.x = x;
    this.y = y;
  }
}
var p1 = new Point(100, 100);
console.log(p1);

class ColorPoint extends Point{
  constructor(x, y, color){
    super(x, y);
    this.color = color;
  }
}
var cp = new ColorPoint(50, 50, 'red');
console.log(cp);

//*********************************************

//輸出繼承關系
console.log(cp instanceof ColorPoint); //true
console.log(cp instanceof Point);  //true

console.log(typeof Point);  // function
console.log(typeof ColorPoint);  // function

//Point(100, 100); //Error

//************************************
//標准的函數可以先寫調用語句,后寫申明語句。因為會定義前置
foo();
function foo(){}

//如果是class呢?
//new Foo(); //Error,Foo is not defined
class Foo{}


//*******************************************

function funThatUseBar(){
  new Bar();
}
//funThatUseBar(); //Error,Bar is not defined
class Bar{}
funThatUseBar(); //ok

2、類中的主體

ES6中、class的主體只能包含方法,不能包含數據屬性。如果在類中包含變量定義,則會報錯。class中的方法有三種類型:構造函數、靜態方法、原型方法,如:

class Class1{
  //構造
  constructor(options){

  }

  // 靜態方法,靜態方法用static修飾
  static staticMethod(){
    return 'static method';
  }

  prototypeMethod(){
    return 'prototype method';
  }
}

其中,每個class和class原型的constructor都是相等的,同時class本質也是function

console.log(Class1 === Class1.prototype.constructor) // true
console.log(typeof Class1)  // function

然后我們對類中的方法做測試

var p = console.log;
p(typeof Class1.prototype.prototypeMethod); 
Class1.prototype.prototypeMethod() // 原型方法調用方式
p(typeof Class1.staticMethod);  
Class1.staticMethod() //靜態方法調用方式

Getters 和 Setters 的用法

class Class2{
  get name(){
    return 'jay';
  }
  set name(value){
    console.log('set name = ' + value);
  }
}

var c2 = new Class2();
c2.name = 'hu';  // "set name = hu"
console.log(c2.name); // "jay"

當使用了get和set時,那么針對屬性的get和set會自動調用class中相關的方法。

貼出所有Js代碼:

'use strict'
class Class1{
  //構造
  constructor(options){

  }

  // 靜態方法
  static staticMethod(){
    return 'static method';
  }

  prototypeMethod(){
    return 'prototype method';
  }
}

console.log(Class1 === Class1.prototype.constructor);
console.log(typeof Class1);

var p = console.log;
p(typeof Class1.prototype.prototypeMethod);
p(typeof Class1.staticMethod);

class Class2{
  get name(){
    return 'jay';
  }
  set name(value){
    console.log('set name = ' + value);
  }
}

var c2 = new Class2();
c2.name = 'hu';
console.log(c2.name);

3、類的繼承

簡單的繼承關系,如下:

'use strict'
class Class1{
  toString(){
    return 'parent class.';
  }
}

class SubClass extends Class1{
  toString(){
    return 'sub class.';
  }
}

var sc = new SubClass();
console.log(sc.toString()); // "sub class"

其中,sc是Class1的實例,也是SubClass的實例:

console.log(sc instanceof Class1); //true
console.log(sc instanceof SubClass); //true

如果要調用父類的方法,怎么辦呢?

class SubClass2 extends Class1{
  toString(){
    return super.toString();
  }
}

var sc2 = new SubClass2();
console.log(sc2.toString());

在繼承關系中,子類的原型等於父類:

console.log(Object.getPrototypeOf(SubClass2) === Class1); //true

在子類中訪問父類構造,使用super即可。

其他

  1. 如果想一覽所有的ES6新特性,可以參考https://github.com/lukehoban/es6features
  2. 如果想系統的學習ES6,那么推薦http://es6.ruanyifeng.com/
  3. 想了解更多Classes in ECMAScript 6,可參考http://www.2ality.com/2015/02/es6-classes-final.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM