iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Modern Web

連我阿公都會-手把手教你架網站 系列 第 14

【Day14】Javascript物件設計!我所知道的物件導向。

  • 分享至 

  • xImage
  •  

本篇,我們要提到的是程式語言中,非常重要的概念 —— 物件導向

聽著好像很複雜,其實我們現實生活都充滿了物件導向的概念。淺顯一點地解釋,便是把細小的東西以「物件」來分組 ── 舉個例子,便是筆電。筆電包含了螢幕、鍵盤、主機板、顯卡、記憶體…數也屬不清的元件。但不論如何,我們使用的都是「一整個筆電。」

使用貼近日常的例子來解釋完畢物件導向的概念後,我們要來談談物件導向的優點:

物件導向的優點


物件導向程式設計(Object-Oriented Programming,OOP)具有多種優點,使它成為我們在開發軟體時的首選方法之一,以下將會列出OOP的幾個主要優點:

  1. 模組化(Modularity)
    物件導向能夠使我們把程式碼分成小塊,且每個塊都有自己的功能。這種方法讓我們可以獨立地開發和測試這些小塊,然後再把它們組合起來,建造出大的程式。這讓程式更容易維護和重複使用。

  2. 繼承(Inheritance)
    OOP的繼承,能夠允許我們建立一個新的類別(稍後下方會提及),可以繼承一個或多個現有的類別的屬性和功能。這樣可以更輕鬆地重複使用程式碼,同時還能建立更通用和更抽象的類別。

  3. 多態(Polymorphism)
    物件導向的多態性,能讓一個類別的實例在不同的情況下表現出不同的行為。這使得我們可以寫出更靈活且更通用的程式,以處理不同種類的對象。

  4. 易於理解和維護
    OOP模擬,並且讓程式碼更像現實世界中,不同物件與物件間的關係。這讓我們更容易理解,也降低了程式碼的難度,減少錯誤,同時也提高了可維護性。

  5. 可重用性
    通過創建通用的類別和方法,我們可以在不同專案中重複使用它們,以節省時間和資源。

  6. 擴展性
    物件導向讓我們可以在添加新的類別和功能時,而不需要改變現有的程式碼。這支持了程式的增量開發和擴展。

  7. 團隊協作
    物件導向通過將程式碼組織成類別和物件,能有助於多個開發者在專案中一起工作。每個開發者都可以獨立地開發和測試他們所負責的部分。

  8. 抽象和模板
    物件導向支持抽象概念,允許開發人員定義介面、抽象類和模板,即定義通用的設計模式和解決問題的方法。

總而言之,OOP雖然提供了一種有組織、可維護和可擴展的方法來開發軟體,提高了程式碼的品質並加速開發時程。好用是好用,但我們還是會依該專案的性質和需求來選擇使用OOP或其他撰寫方式,如 函數語言(functional programming)。

回到本次鐵人賽的主軸 ── 網頁設計。為甚麼會突然提到物件導向呢?因為在本日的文章中,我將教您使用物件導向的方法去撰寫JavaScript的物件程式!

何謂類別?類別的概念


假設我們現在要定義一個人 ── 一個人是甚麼概念呢?
https://ithelp.ithome.com.tw/upload/images/20230929/201604886Y1YNKxKbs.png

一個人有名字、身高、體重…等,這都是一個人的 屬性
而身為一個人,我們會講話、會走路、會跑步,這都是一個人的 方法
https://ithelp.ithome.com.tw/upload/images/20230929/2016048824HcNgrGKi.png

再舉一個例子 ── 我們在路邊看到一台卡車。
我們可以看到構成卡車的物件:有輪子、駕駛座、方向盤…等物件,它們都是這台卡車的 屬性

一台卡車可以被駕駛,原因是因為各種元件的相互扶持,才得以產生這個結果。
https://ithelp.ithome.com.tw/upload/images/20230929/20160488iV7LxvTU2V.png
https://ithelp.ithome.com.tw/upload/images/20230929/20160488pIDB0Xsyfn.png
其實就是把現實的概念套用在程式碼,一開始還是需要花一點時間去理解的。

建構類別 / 使用物件


使用物件前,我們要先建立類別:

  • 建立類別(Class)
    這裡我們建立了一個Person類別,並給予其參數:名字、年齡、體重…等值。
class Person {
    name = "rex";
    age = 17;
    weight = 60;
    height = 170;
}
  • 使用物件
    要建立一個物件我們會使用 new 語法:
    變數 = new 物件();
rex = new Person();

建構完畢後,我們便能使用這個物件了:

rex = new Person();
// 讀値
console.log(rex);
console.log(rex.name);
console.log(rex.age);
console.log(rex.weight);
console.log(rex.height);
// 設値
rex.height = 180;
console.log("\n"+rex.height);

這裡我們宣告了一個Person物件,由rex變數儲存著,我們可以透過rex變數呼叫物件下的值。
https://ithelp.ithome.com.tw/upload/images/20230929/20160488UpETQUmGkm.png

  • 建構子

我們在建構物件時,也可以把資料傳進去我們的物件內:

rex = new Person("傳入值","傳入值","傳入值","傳入值"....);

我們可以這樣寫:意思是把 constructor 後方括號的資料,存到物件裡面。

class Person {
    name = "rex";
    age = 17;
    weight = 60;
    height = 170;

    constructor (name,age,weight,height) {
		console.log("Person物件建構")
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.height = height;
    }
}

程式碼中的 this 語法,可以將其理解為 自己的 的意思。

  • this.name = name; 意指:把自己的name設定為從建構子傳入的值
    https://ithelp.ithome.com.tw/upload/images/20230929/20160488C9dhylA3tD.png
rex = new Person();
console.log(rex);

viscose = new Person("viscose",19,60,180);
console.log(viscose);

這裡我們分別建立了兩個Person物件,可以發現一個Person物件的值都是undefined,是因為我們在建立第一個rex物件時,我們沒有對他傳入任何值。
https://ithelp.ithome.com.tw/upload/images/20230929/20160488vPvIZefmLj.png

要解決這個問題,我們可以在把參數存進去的前面加一個判斷,如果有值的話再存入物件中。

class Person {
    name = "rex";
    age = 17;
    weight = 60;
    height = 170;

    constructor (name,age,weight,height) {
        if (name) this.name = name;
        if (age) this.age = age;
        if (weight) this.weight = weight;
        if (height) this.height = height;
    }
}

https://ithelp.ithome.com.tw/upload/images/20230929/20160488kt2N2O71mp.png
這樣就正常許多。

  • 方法 Methods
    我們可以在物件裡撰寫function。
class Person {
    name = "rex";
    age = 17;
    weight = 60;
    height = 170;

    constructor (name,age,weight,height) {
        if (name) this.name = name;
        if (age) this.age = age;
        if (weight) this.weight = weight;
        if (height) this.height = height;
    }

    hello () {
        console.log("hi, my name is "+ this.name);
    }
}

調用 hello() 函式:

rex = new Person();
console.log(rex);

viscose = new Person("viscose",19,60,180);
console.log(viscose);

rex.hello();
viscose.hello();

https://ithelp.ithome.com.tw/upload/images/20230929/20160488YFiR9C0h0S.png

  • 靜態函式 static function
    靜態函式是一個不需要宣告變數便可以調用的函式:
console.log(Math.random());

以上就是一個很好的 靜態函式 例子!
我們可以發現我們沒有宣告Math物件就直接call Math物件下的函式。

有靜態函式,當然也有靜態變數。
在下方的案例中,我們定義總人數的靜態變數為 people
定義一 static count() 靜態函式。
並把這一個函式寫到函式的初始化裡,達成每建立一個Person物件 ⇒ people+1。

class Person {
    name = "rex";
    age = 17;
    weight = 60;
    height = 170;

    constructor (name,age,weight,height) {
        if (name) this.name = name;
        if (age) this.age = age;
        if (weight) this.weight = weight;
        if (height) this.height = height;

        // 在這裡

        Person.count();
    }

    hello () {
        console.log("hi, my name is "+ this.name);
    }

    static people = 0;
    static count() {
        this.people++;
    }
}

https://ithelp.ithome.com.tw/upload/images/20230929/20160488FqmH4GxHuV.png

  • 繼承
    同為人類,有的人是上班族,有的人是學生。

要寫在class裡面的話,我們可以這麼撰寫:

class Student extends Person {
    studentId;
    constructor(studentId, name, age, weight, height) {
        super(name, age, weight, height);
        this.studentId = studentId;
    }
    live() {
        this.hello();
        console.log("i love study\n");
    }
}
class OfficeWorker extends Person {
    workId;
    constructor(workId, name, age, weight, height) {
        // person的初始化        
        super(name, age, weight, height);
        this.workId = workId;
    }
    live() {
        // person的hello()函式
        this.hello();
        console.log("i love work\n");
    }
}

https://ithelp.ithome.com.tw/upload/images/20230929/20160488PwvT650Jxe.png


看完上述的範例後,建議您可以多加思考,該如何應用物件導向的特性使程式碼變得更靈活。

初始的想法可以從:「盡量不要撰寫重複的程式碼」開始,來規劃。

物件導向幾乎是每一個程式語言都具備的,例如:Python、Java、C++…等程式語言。這裡還蠻推薦您也接觸並學習C++和Java,因為這兩個程式語言都是我個人覺得上手難度中上的,如果您學起來了,基本上去接觸其他的語言會更快且更加容易上手 ── 那今天的物件導向科普就到這裡啦~!


上一篇
【Day13】讓網頁動起來(3)使用GSAP設計動畫!
下一篇
【Day15】專題實作:簡易計算機
系列文
連我阿公都會-手把手教你架網站 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言