iT邦幫忙

2021 iThome 鐵人賽

DAY 15
3
Modern Web

舌尖上的JS系列 第 15

D15 - 那個圓圓的東西 - OOP 物件導向程式設計

前言

在查詢 MDN 語法關於 string、array、object 的內建方法時,有沒有發現開頭都有 prototype 這個字樣,可是明明在使用上沒有呀!

// MDN 語法
Array.prototype.map()

// 實際使用
['Ritz', 'Lotus', 'Oreo'].filter(chocolate => chocolate.length > 4)

認識 JavaScript 的第一門課,應該聽過這個語言本身是以原型為基礎的物件導向設計,沒錯,prototype 翻譯為原型,在學習 JavaScript 路上不能錯過的一個大大大重點!

推出新款麵包時,若麵包師傅先分享了背後的故事與設計理念,這樣品嚐時是不是會更深刻富有情感連結呢。

比起直接奔向原型、原型鏈,各位小白們,讓我先從當初 JavaScript 的由來說起,再帶到原型物件導向吧。

JavaScript 設計由來

從前從前(講故事起手式),1995 年前的瀏覽器只能進行瀏覽,無法和使用者互動,若是網頁上有一欄「用戶名」要求填寫,瀏覽器無法判斷使用者是否真的填寫完畢,須交由後面的伺服器端來判斷,現在看來,超級浪費時間與資源對吧!當時的網景公司也這麼覺得,他們需要一種網頁腳本語言來實現與瀏覽器的互動,基於這個需求,由工程師 Brendan Eich 負責,JavaScript 因此誕生。

當時 1994 年物件導向程式設計 OOP 概念正夯,可說是歸功於當時最流行的語言 C++,Brendan Eich 也跟上這股潮流,將物件導向程式設計帶入 JavaScript,但是與其他使用 class 類別達到繼承的語言不同, JavaScript 採用了以原型為基礎的物件導向設計。

那,什麼是 物件導向程式設計

物件導向程式設計 Object-Orient Programing (OOP)

與傳統的程式設計主張將程式看作一系列函式的集合不同,物件導向程式設計 OOP 是一種是以物件概念為主的程式設計思維,將物件作為程式的基本單位,彼此獨立且能互相呼叫,其中的每一個物件都應該能夠接受資料、處理資料並將資料傳達給其它物件。

重要的物件導向程式語言包含: Common Lisp、Python、C++、Objective-C、Smalltalk、Delphi、Java、Swift、C#、Perl、Ruby、JavaScript 與 PHP等。

雖然這些程式語言都使用了 OOP 設計,但也因不同的風格而有所差異,這裡介紹兩種風格:類別基礎(Class-based)與原型基礎 (Prototype-based)

  • 類別基礎(Class-based):Java、C++
  • 原型基礎(Prototype-based):JavaScript

基於類別 class-based programming

基於類別 class-based 的物件導向語言,物件必須透過 類別 Class才能被創造出來,以此創出來的物件都稱為該類別的 實例 instance

以蓋房子舉例:類別 Class 就是設計圖,不同設計圖蓋出來的房子造型都不相同,若A版設計圖上畫了房子有 10 層樓、尖尖的屋頂、大大的落地窗,依照 A 版設計圖蓋出的房子,就稱為 A 版設計圖的 實例 instance,每棟房子都是參照設計圖建造出來的,這個過程稱為 實體化 instance

  • 類別 Class:用來定義某一種物件所擁有的屬性,類別 Class 是抽象的事物,例:房子設計圖,定義了房子要有的設計,但並不是真的房子。

  • 實例 Instance:透過類別 Class產生出的實體,例:依照設計圖建造的房子。

subClass

class-based 的物件導向語言中,類別 Class有專屬的定義方式並且有層級概念,生成了第一個 類別 Class後,可以再生成第二個 類別 Class 成為第一個類的子類 subClass,第二個類會繼承第一個類中定義的屬性。

基於原型 prototype-based programming

基於原型 prototype-based programming 的語言並不存在 類別 Class實體 instance的差異:它只有物件。

不具有 類別 Class 的 JavaScript 怎麼創造物件呢?
也是使用 new + 建構式,但這裡的建構式與 class-based 語言使用 類別 Class 的建構器不同,因此就算 ES6 新增了一個 class 保留字用來當 Constructor 創建 實體 instance,也**不代表它的物件導向的方式會變成 Class-Based,只是被 Class 包裝的 Prototype-Based 而已。
Class 只是簡化了 JavaScript 中操作 Constructor 的語法糖而已。

因此為了實現繼承的概念,加上 原型 prototype使 實例 instance 可以獲得此原型物件上的屬性,任何物件都可以指定其自身的屬性,在創建時或運行時都可以。

Class-based & Prototype-based 比較

基於類別 Class based (Java) 基於原型(JavaScript)
類別和實例是不同的事物。 所有物件均為實例。
通過類別定義來定義類;通過建構函數來產生實體。 通過建構函數來定義和創建一組物件。
通過 new 操作符來創建物件。 相同。
通過類別定義來定義現存類的子類,從而建構物件的層級結構。 通過將一個物件作為原型,指定關聯於建構函數來建構物件的層級結構。
遵循類別鏈繼承屬性。 遵循原型鏈繼承屬性。
類別定義指定類別的所有實例的所有屬性。 無法在運行時添加屬性。
建構函式或原型指定初始的屬性集。 允許動態地向單個的物件或者整個物件集中添加屬性,或者從中移除屬性。

Reference

你所不知道的JS
深入了解物件模型
Javascript继承机制的设计思想
从设计初衷解释 JavaScript 原型链
物件導向程式設計
基於原型編程
類別為基編程
程式語言的特性本質(二)類別與原型的物件管理學
物件導向--基於類別與原型的範例

結語

相信看完以上能區分原型的物件導向概念,明天就可以解答一開始的問題,進一步講 prototype 的用法。


上一篇
D14 - 服務生!我要 this this this
下一篇
D16 - 那個圓圓的東西 - 物件原型 & 原型鏈
系列文
舌尖上的JS30
0
MJ
iT邦新手 5 級 ‧ 2021-09-30 21:14:15

這個超重要喔!我之前就是不知道物件導向是蝦餃,每天都不知道在寫蝦餃/images/emoticon/emoticon02.gif

Hooo iT邦新手 5 級 ‧ 2021-10-01 17:03:46 檢舉

是不是!我也是最近補起來
蝦餃 ??? 很適合當舌尖系列的文章名字誒

0
Chiahsuan
iT邦新手 4 級 ‧ 2021-09-30 21:29:41

比較表格直接複製起來~~~廣送親友/images/emoticon/emoticon12.gif

Hooo iT邦新手 5 級 ‧ 2021-10-01 17:04:26 檢舉

表格是取自MDN ~~

0
wendy
iT邦新手 4 級 ‧ 2021-09-30 22:56:58

下次記得取葡萄

Hooo iT邦新手 5 級 ‧ 2021-10-01 17:04:42 檢舉

我覺得隊長的蝦餃比較好欸

1
jerrythepotato
iT邦新手 5 級 ‧ 2021-10-01 02:17:44

寫得相當簡短精要呢!

請問後續會比較js物件的建構函式和類別函式(classes)兩者之間的取捨嘛?

因為沒寫過較龐大複雜的程式碼,在一般撰寫上,兩者都能拿來作使用,也都能有繼承行為,覺得光是能使用prototype就已經有大的操作空間了

Hooo iT邦新手 5 級 ‧ 2021-10-01 17:09:11 檢舉

之後會寫到 class 的介紹,但我也還在學習中沒有實際比較過和 constructor 的差異,在查找文章的過程如果有看到相關介紹再整理分享在文章內!謝謝你的留言:)

我要留言

立即登入留言