ES6新特性5:類(Class)和繼承(Extends)

本文摘自ECMAScript6入門,轉載請註明出處。es6

 

1、類(Class)編程

  1.基本語法數組

  JavaScript語言的傳統方法是經過構造函數,定義並生成新對象。下面是一個例子數據結構

function Point(x, y) {
    this.x = x;
    this.y = y;
}

Point.prototype.toString = function () {
    return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

 

  ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,做爲對象的模板。經過class關鍵字,能夠定義類。基本上,ES6的class能夠看做只是一個語法糖,它的絕大部分功能,ES5均可以作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼用ES6的「類」改寫,就是下面這樣。函數

//定義類
class Point {
    constructor(x, y) {    //constructor 構造方法 this.x = x;
        this.y = y;
    }

    toString() {
        return '(' + this.x + ', ' + this.y + ')';
    }
}

var p = new Point(1, 2);

  構造函數的prototype屬性,在ES6的「類」上面繼續存在。事實上,類的全部方法都仍是定義在類的prototype屬性上面。this

 

  2.constructor方法spa

  constructor方法是類的默認方法,經過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,若是沒有顯式定義,一個空的constructor方法會被默認添加。prototype

 

2、繼承(Extends)code

  Class之間能夠經過extends關鍵字實現繼承,這比ES5的經過修改原型鏈實現繼承,要清晰和方便不少。對象

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y); // 調用父類的constructor(x, y)
        this.color = color;
    }

    toString() {
        return this.color + ' ' + super.toString(); // 調用父類的toString()
    }
}

  上面代碼中,constructor方法和toString方法之中,都出現了super關鍵字,它在這裏表示父類的構造函數,用來新建父類的this對象。

  子類必須在constructor方法中調用super方法,不然新建實例時會報錯。這是由於子類沒有本身的this對象,而是繼承父類的this對象,而後對其進行加工。若是不調用super方法,子類就得不到this對象。

 

3、原生構造函數繼承

  原生構造函數是指語言內置的構造函數,一般用來生成數據結構。ECMAScript的原生構造函數大體有下面這些。之前,這些原生構造函數是沒法繼承的。

  • Boolean()
  • Number()
  • String()
  • Array()
  • Date()
  • Function()
  • RegExp()
  • Error()
  • Object()

  ES6容許繼承原生構造函數定義子類,由於ES6是先新建父類的實例對象this,而後再用子類的構造函數修飾this,使得父類的全部行爲均可以繼承。下面是一個繼承Array的例子。

class MyArray extends Array {
    constructor(...args) {
        super(...args);
    }
}

var arr = new MyArray();
arr[0] = 12;
arr.length // 1

arr.length = 0;
arr[0] // undefined

  上面代碼定義了一個MyArray類,繼承了Array構造函數,所以就能夠從MyArray生成數組的實例。這意味着,ES6能夠自定義原生數據結構(好比Array、String等)的子類,這是ES5沒法作到的。

 

4、Class的Generator方法

  若是某個方法以前加上星號(*),就表示該方法是一個Generator函數。

class Foo {
    constructor(...args) {
        this.args = args;
    }
    * [Symbol.iterator]() {
        for (let arg of this.args) {
            yield arg;
        }
    }
}

for (let x of new Foo('hello', 'world')) {
    console.log(x);
}
// hello
// world

 

上面代碼中,Foo類的Symbol.iterator方法前有一個星號,表示該方法是一個Generator函數。Symbol.iterator方法返回一個Foo類的默認遍歷器,for...of循環會自動調用這個遍歷器。

 

5、Class的靜態方法

  類至關於實例的原型,全部在類中定義的方法,都會被實例繼承。若是在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接經過類來調用,這就稱爲「靜態方法」。

class Foo {
    static classMethod() {
        return 'hello';
    }
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

  上面代碼中,Foo類的classMethod方法前有static關鍵字,代表該方法是一個靜態方法,能夠直接在Foo類上調用(Foo.classMethod()),而不是在Foo類的實例上調用。若是在實例上調用靜態方法,會拋出一個錯誤,表示不存在該方法。

  父類的靜態方法,能夠被子類繼承。

class Foo {
    static classMethod() {
        return 'hello';
    }
}

class Bar extends Foo {
}

Bar.classMethod(); // 'hello'

  上面代碼中,父類Foo有一個靜態方法,子類Bar能夠調用這個方法。

相關文章
相關標籤/搜索