你懂 JavaScript 嗎?#18 (簡易版)物件導向概念

你所不知道的 JS

本文主要會談到簡單的物件導向概念,作為後續「原型」(Prototypes)的暖身。

類別(Class)、建構子(Constructor)、實體(Instance)

「類別」可想像成是建構某特定物體的藍圖或模具,而「實體」就是按照這藍圖或模具製造出來的成品。這當中需要使用類別的一個特殊方法「建構子」來做初始化的動作。

藍圖

虛擬碼如下,Person 是一個類別,利用與類別同名的建構子 Person 做初始化,進而建立出實體 Jack。

class Persion {
  career = null;

  Persion(job) {
    career = job;
  }

  sayHi() {
    pring('Hello, I am a/n', career);
  }
}

Jack = new Persion('engineer');
Jack.sayH(); // 'Hello, I am a/n engineer'

在真實的世界裡,JavaScript 用什麼方式呈現呢?舉個最簡單的例子。

const str = new String('Hello World');
str.length // 11

String 是個類別方法,在這裡當建構子用,任何給定的字串都是這個類別的實體,它幫我們包裝了可在這個字串上執行的各種功能。因此,str 是 String 的實體,可執行 str.length 取得字串長度。

不過,在 JavaScript 的世界中,並沒有真正的類別的概念,只能使用設計模式(design pattern)來模擬,我們在稍後的原型中會看到各種解法與優劣討論。

繼承(Inheritance)

定義一個類別,其 特性繼承(也可說是擴充 extend)自另外一個類別,稱它們為「父類別」與「子類別」,其中,子類別繼承了父類別的特性。

父與子

如下,CoolPerson 繼承自 Person,其中 sayHi 繼承了來自 Person 的方法並做覆寫。

class Persion {
  career = null;

  Persion(job) {
    career = job;
  }

  sayHi() {
    pring('Hello, I am a/n', career);
  }
}

class CoolPerson inherits Person {
  sayHi() {
    inherited: sayHi();
    pring('I love my job!');
  }

  eat(food) {
    pring('I am eating...', food);
  }
}

「多重繼承」(multiple inheritance)是指子類別可繼承一個以上的父類別,但由於 JavaScript 並沒有提供原生機制來處理這種情況,因此不做討論。

多型(Polymorphism)

「多型」是指子類別除了擁有自己的方法外,這個方法還能覆寫來特化父類別的同名方法,以賦予其更特殊的行為。

如上,CoolPerson 的 sayHi 與其父類別 Person 的 sayHi 同名,它使用 inherited: sayHi() 參考它所繼承且未被覆寫的父類別同名方法並作呼叫,接著加上 pring('I love my job!') 這個屬於它自己的功能。其中,不指定參考哪一層的父類別(可能是祖父類別 XD)的方式稱為「相對多型」,而若有指名是哪層父類別的方法,那就是「絕對多型」了。

回顧

看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到…

References


本篇文章真的滿短的…下一篇會將本篇提到的概念以更具體的方式說明,敬請期待。

謝謝大家


同步發表於2019 鐵人賽


You-Dont-Know-JS javascript 你所不知道的JS 2019鐵人賽 你懂JavaScript嗎? 鐵人賽 You-Dont-Know-JS-this-and-Object-Prototypes 你懂 JavaScript 嗎?2019 iT 邦幫忙鐵人賽 系列文