iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 25
0
Modern Web

JavaScript Note系列 第 25

class 類別

  • 分享至 

  • xImage
  •  

JavaScript能夠透過原型來實現繼承,而非使用傳統的類別,這點,讓許多的開發人員一開始的確是霧煞煞,非常地不習慣。

先撇除原型繼承這樣的方式所帶來的好壞,畢竟使用類別來實現繼承已經有相當長的一段時間,不管是技術上或是理論上的,可說是相當地成熟,所以JavaScript不可避免地也走上同樣的道路,甚至出現了類似傳統物件繼承的函式庫,有鑑於此,在ES6版本總算將傳統物件繼承的語法給標準化,讓我們可以在JavaScript使用class關鍵字。

請注意,class關鍵字在JavaScript是語法糖,JavaScript骨子裡仍然使用原型作為繼承的執行方式,即便如此,我想那些熟悉後端程式語言的開發者,在前端看到class關鍵字,心理應該很高興才是。

語法糖
https://zh.wikipedia.org/zh-tw/%E8%AF%AD%E6%B3%95%E7%B3%96

class Member {
    constructor(_name) {
        this.name = _name;
    }
    greeting() {
        console.log(`Hello!${this.name}`);
    }
}
let mem1 = new Member('Mary');
mem1.greeting(); //Hello!Mary
console.log(mem1 instanceof Member); //true

使用class關鍵字建立Member類別。
定義建構子constructor( ),建立物件的同時,初始化物件,指定name屬性值。
定義方法greeting( )。
使用new關鍵字,建立mem1物件。

比對ES5的寫法:

function Member(_name) {
    this.name = _name;
}
Member.prototype.greeting = function () {
    console.log(`Hello!${this.name}`);
}

個人是比較推薦ES6的class。

靜態方法

上面的範例,不管是ES5函式建構或ES6 class定義的方法,都是屬於物件層級,也就是說,只有創立新物件,才能使用定義的方法。

除此之外,我們也可以定義類別層級的方法,直接在類別就可以使用定義的方法,無須再創立新物件。

class Member {
    constructor(_name) {
        this.name = _name;
    }
    greeting() {
        console.log(`Hello!${this.name}`);
    }
    static run() {
        console.log('running...');
    }
}
let mem1 = new Member('Mary');
mem1.greeting();
mem1.run();

在run( )前加上static關鍵字,表示run( )為類別層級的方法。
由於run( )為類別層級,所以無法透過mem1物件存取。
https://ithelp.ithome.com.tw/upload/images/20181109/20112573ToxnyrspYF.png
只能透過Member類別存取。

Member.run(); //running...

繼承

class Person {
    constructor(_name) {
        this.name = _name;
    }
    run() {
        console.log(`${this.name} is running...`);
    }
}
class Member extends Person {
    constructor(_name, _age) {
        super(_name);
        this.age = _age;
    }
    greeting() {
        console.log(`${this.name} is ${this.age}`);
    }
}
let mem1 = new Member('Mary', 18);
mem1.greeting(); //Mary is 18
mem1.run(); //Mary is running...

先定義Person類別,再定義Member類別,並利用extends關鍵字,使Member類別繼承Person類別,此時Person類別為基底類別,Member類別為衍生類別。

Member類別的建構子,可以透過super關鍵字,呼叫基底類別(Person)的建構子,並傳送參數_name。
藉super來定義由Member類別建立的物件的name屬性。
而Member物件的age屬性,則是由自身的建構子定義的。

由於Member類別繼承自Person類別,所以Member物件可以存取Person類別中,定義的run( )函式。

由結果可以看出mem1,具有name屬性,也可以存取run( ),這就是繼承的最大用意。
可以讓我們的程式具備重複利用性以及擴充性的優點。

但如果,使用Person類別建立物件,由於mem2物件不是由Member類別建立的,所以它自然沒有age屬性,以及無法存取greeting( )函式。

let mem2 = new Person('Bill', 18);
console.log(mem2.age);
mem2.run();
mem2.greeting();

結果
https://ithelp.ithome.com.tw/upload/images/20181109/20112573wYLPgeKKzG.png

參考來源:
忍者:JavaScript開發技巧探秘


上一篇
prototype chain 原型鏈 & inherit 繼承
下一篇
callback function
系列文
JavaScript Note31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言