< 返回 Alpha Camp 全學期心得
得過諾貝爾物理獎的理查 費曼(Richard Feynman)曾說,如果你能將一個概念教給小孩子,並且他也能理解。這表示你真的理解這個議題的概念了。
為確認自己是否理解物件導向,這篇文章將試圖使用費曼技巧(註1)來說明物件導向揪竟是怎麼一回事。
物件導向是什麼
物件導向程式設計 (Object-oriented programming),簡稱OOP。是一種程式設計方法:由模型造出一群物件,並且物件之間可以互動。

模型內包含兩樣東西:property(屬性) 與 method (功能、方法)。模型造出的物件稱為instance (實例),也都會包含property與method。
舉例來說,我們可以設計一支手機模型property、method有:
- property:brand, price, screen size, ram, … 等
- method:call, send message, remote controll, watch video…等
於是我們至少能做到兩件事:
- 造出不同的手機
當brand帶入不同廠牌時,如:Apple, Samsung,我們會分別得到蘋果、三星的手機。
- 手機與其他物件的互動
method: remote controll,可以控制其他家電(物件)
因此用物件導向設計程式時,非常仰賴抽象化的能力,我們需要對現實生活中的物品,將它的外觀特徵及能做的行為抽象成property與method。
(費曼技巧到此為止。抱歉了…小朋友)
如何在JavaScript中實作物件導向
(接下來會使用一連串的術語,因此需要一點程式基礎較能理解)
在ES6引入了class (類別)後,儘管本質不同(註2),但也能更輕易做出看似 Java 這類 Class-Based 的物件導向程式碼了。
Class組成的物件導向架構
- Class (模型),包含Constructor (屬性) 與 Prototype (方法)
- Constructor:負責製造名詞,即上述的property。
- instance (實例),即上述的物件
- Prototype:包含各種動詞,可想像為招式庫。
- 各個function,即上述的method。
- Constructor:負責製造名詞,即上述的property。

Constructor (屬性)
1. Constructor通常只放屬性,不放方法。
所以不太會出現下面這樣的程式碼
class SmartPhone {
constructor(name, price) {
this.name = name
this.price = price
//較不會在 constructor內放進funtion
this.showPhoneInfo = function () {
console.log(`The price of ${this.name} is ${this.price}.`)
}
}
}
2. new造出instance、constructor.name查詢造出此instance的constructor
//new造出instance
let alphaPhoneX = new SmartPhone('alphaPhoneX', 14999)
//查出造instance的constructor
console.log(alphaPhoneX.constructor.name)
3. Prototype Chain (原型鏈)
描述產生此物件的原型的族譜過程。
可用getPrototypeOf查出原型,一直查到結果null時,它就是最源頭的原型。
比如:
let number = 3 //
let prototypeOfNumber = Object.getPrototypeOf(number) // object created by Number()
let prototypeOfPrototypeOfNumber = Object.getPrototypeOf(prototypeOfNumber) // object created by Object()
let prototypeOfPrototypeOfPrototypeOfNumber = Object.getPrototypeOf(prototypeOfPrototypeOfNumber) // null
- number其實是一個由 Number()函式建立的instance
- 而 Number()函式本身也是一個instance,追朔 Number()的原型是 Object()
- 而Object()函式再往上追,會追到null (空值),代表它就是最源頭的原型
這邊很容易搞混,getPrototypeOf 的prototype並不是class裡的方法,而是指造出這個instance的模型(class或constructor)。
而上述例子的兩個函式Number()、Object(),都是由JavaScript的創世神一開始預設寫好在程式裡頭的,因此我們得以對number賦值為3。
Prototype (方法)
1. 建立Prototype
使用Class.prototype 建立出prototype
class SmartPhone {
constructor(name, price) {
this.name = name
this.price = price
}
}
//建立prototype
SmartPhone.prototype.showPhoneInfo = function() {
console.log(`The price of ${this.name} is $${this.price}.`)
}
let alphaPhoneX = new SmartPhone('alphaPhoneX', 14999)
alphaPhoneX.showPhoneInfo() //'The price of alphaPhoneX is 14999.'
2. 由同一個class建立的instance,會共用同樣的prototype
let alphaPhoneX = new SmartPhone('alphaPhoneX', 14999)
let alphaPhoneY = new SmartPhone('alphaPhoneY', 18900)
let alphaPhoneZ = new SmartPhone('alphaPhoneZ', 23900)
alphaPhoneX.showPhoneInfo() //'The price of alphaPhoneX is 14999.'
alphaPhoneY.showPhoneInfo() //'The price of alphaPhoneY is 18900.'
alphaPhoneZ.showPhoneInfo() //'The price of alphaPhoneZ is 23900.'
物件導向的優與劣
首先,我們來比較有無使用物件導向的差別:

同樣三支手機的程式碼,使用物件導向只需要17行程式碼(還包含註解),沒有使用物件導向卻需要26行程式碼。
物件導向的優點
- 讓程式碼可以重複利用
- 簡化主程式邏輯,將細節隱藏在物件內
- 讓程式碼更簡短、易於維護並降低「閱讀程式碼」需花費的時間
物件導向的缺點
- 門檻較高,了解物件導向本身需要花費較多時間
- 寫簡單程式相比傳統寫法,需要寫出更多程式碼
總結
物件導向這個概念:
- 學會之前,概念有點艱深,不容易懂
- 學會之後,能簡化程式碼,更易於維護及閱讀
- 太簡單的問題,用物件導向反而會將問題變複雜

參考資料
其他
< 返回 Alpha Camp 全學期心得