iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
0
Modern Web

重新學習網頁設計系列 第 10

DAY 10. JavaScript 類別與物件

DAY 10. JavaScript 類別與物件

物件導向程式設計(OOP)已經存在多年
物件是一種在邏輯上與一群資料及功能有關的東西
它的設計,是為了對應我們對這個世界的理解方式

引用: JavaScript 學習手冊

定義類別

ES6之後我們能用簡潔的方式定義類別

class Car {
    constructor() {
        //
    }
}

// 建立實例
const car1 = new Car()
const car2 = new Car()

console.log(car1 instanceof Car)    // true
console.log(car2 instanceof Car)    // true
console.log(car1 == car2)           // false

說明
範例中定義了Car類別,接著定義兩個實例car1, car2
接著我們使用instanceof驗證該實例屬於Car類別
最後我們測是兩個Car實例是否相等,結果不相等

物件永遠不相等

類別屬性以及方法

class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
        this.height = '165cm'
    }

    say(content) {
        console.log(content)
    }
}

// 建立實例
const Peter = new Person('Peter', 20)
console.log(Peter)
// [object Object] {
//   age: 20,
//   height: "165cm",
//   name: "Peter"
// }

Peter.height = '170cm'
console.log(Peter.height)   // "170cm"
Peter.say('Hello')  // "Hello"

說明
建立實例後我們能夠輕易地修改屬性來更改狀態
所有的方法都會是該實例prototype

靜態方法(類別方法)

靜態方法是執行與整個類別有關的工作,而不是針對實例

class Person {
    constructor(name, age) {
        this.name = name
        this.age = age
        this.idNumber = undefined
    }

    static generateIdNumber() {
        let idNumber = ''
        const texts = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        for (let i = 0; i < 10; i++)
            idNumber += texts.charAt(Math.floor(Math.random() * texts.length))
        return idNumber
    }
}

const Sam = new Person('Sam', 1)
Sam.idNumber = Person.generateIdNumber()
console.log(Sam)
// [object Object] {
//   age: 1,
//   idNumber: "7OFL1VSJ5N",
//   name: "Sam"
// }

說明
PersonSam出生時我們使用大家通用的生份正規則來產生idNumber
由於全國人民的身分證產生規則都一樣,因此generateIdNumber方法屬於Person類別
而非實例Sam

繼承

類別是有階層之分的,例如汽車與機車屬於交通工具;狗與貓屬於動物
當有階層之分時我們就能夠透過繼承來將共通特性抽離至父類別

class Transportation {
    constructor() {
        this.passengers = []
        this.maxPassengers = 2
    }
    addPassenger(person) {
        if(this.passengers.length == this.maxPassengers) {
            console.warn('too much person.')
        } else {
            this.passengers.push(person)
        }
        return this.passengers
    }
}

class Car extends Transportation {
    constructor() {
        super()
        this.maxPassengers = 4
    }
}

class Autobike extends Transportation {
    constructor() {
        super()
        this.maxPassengers = 2
    }
}

const myCar = new Car()
console.log(myCar.constructor.name)     // Cart
console.log(myCar instanceof Transportation)    // true

const myBike = new Autobike()
console.log(myBike.constructor.name)    // Autobike
console.log(myBike instanceof Transportation)    // true

console.log(myCar.addPassenger('a'))    // ["a"]
console.log(myCar.addPassenger('b'))    // ["a", "b"]
console.log(myCar.addPassenger('d'))    // ["a", "b", "d"]
console.log(myCar.addPassenger('e'))    // ["a", "b", "d", "e"]
console.log(myCar.addPassenger('f'))    // "too much person."
                                        // ["a", "b", "d", "e"]

console.log(myBike.addPassenger('a'))   // ["a"]
console.log(myBike.addPassenger('b'))   // ["a", "b"]
console.log(myBike.addPassenger('c'))   // "too much person."
                                        // ["a", "b"]

說明

範例中CarAutobike都可以增加乘客
因此我們把**addPassenger定義於Transportation
但由於不同的交通工具乘客成載量並不相同,因此在子類別建構是中複寫父類別的屬性值

我們能夠在子類別建構子constructor中使用super來繼曾父類別建構子constructor
接著在子類別中定自己的屬性,而若屬性已經定義於父類別則會蓋過類別的屬性
因此我們可以針對不同的子類別定義相同屬性但卻不同數值來因應現實環境的需求

父類別有時亦被稱為超類別

更完整的物件操作請參考MDN JavaScript 物件導向介紹


上一篇
DAY 9. JavaScript Array 操作
下一篇
DAY 11. JavaScript Map and Set
系列文
重新學習網頁設計30

尚未有邦友留言

立即登入留言