前言
這節要來研究一下如何使用 ES6 新增的 class 實作出物件導向的範例,以及尚未出現 class 時,是如何處理這部分的?
ES6 新增的 class
直接看程式碼
1 | class dog { |
ES6 新增的 class
就像是一張設計圖,沒使用建構子 new
之前是沒有辦法使用的。
以這個例子來說,我們要建立狗的類別,所以我們定義了三個函式,其中 constructor
函式比較特別,當使用建構子 new
實例化 (instance) 狗的 class
時,可在括號內放入參數,而 constructor
函式可以取得該參數。
這個例子中以這樣的方式初始化每隻狗的名字,而我們可以更進一步的觀察
- 此時的變數
d
與變數b
使用typeof
觀察會是物件 - 以此設計圖新增的每隻狗都有定義在設計圖內的函式
- 使用三等號比較兩者的
sayHello
方法,會回傳true
,代表為同個函式。
ES5 沒有 class 的作法
1 | function dog(name){ |
可以發現差別並不大,直觀來說下半部的程式碼幾乎是一樣的。
主要就是需要宣告一個函式,而這個函式其實就是 ES6 class
內的 constructor
函式。
而在 ES5 的時候,是看使用時有沒有加入建構子 new
來決定是否為 constructor
函式或是一般的函式。
然後除了要宣告一個函式之外,也必須在該函式的 prototype
定義這些狗會做什麼。
接下來進行一些觀察,可以得知跟上面那個例子的結果是一樣的。
至於 prototype
究竟是什麼,下一節才會提到。
ES5 奇怪部份推薦的做法
這部分我可能之後會去找一下答案,不太清楚箇中差異,但個人蠻喜歡這樣的做法,因為我覺得蠻好懂的,畢竟就是物件罷了。
1 | var cat = { |
像這樣,建立一個貓物件,然後裡面定義一些方法。
接著使用 Object.create()
,這樣就結束了。
觀察後半部印出的內容,結果也與使用 class
實作出來的差別無異。
對照一下兩者內容:
而我的疑問是:
- 以這個範例來說,可以算是物件導向的範例嗎?
我想應該是,畢竟也有達成 MDN 對於物件導向程式設計的敘述 - 從對照圖可以看出結構不太一樣,但我不太清楚這兩種實作方式的優劣,在實務上會推薦使用哪一種呢?
後來我找到了這兩篇
- [筆記] 談談JavaScript中最單純的原型繼承(prototypal inheritance)─ Object.create
- 談談 JavaScript 中的 function constructor 和關鍵字 new
- 繼承與原型鏈
然而也想起為何奇怪部分的影片講師會比較推薦 Object.create()
的方式,以下截自上述連結文章內描述。
在其它的程式語言中,會用 class 這個關鍵字來設定該物件要長什麼樣子,然後透過關鍵字
new
來建立物件。
然而,和其他程式語言不同的地方在於,JavaScript 實際上使用的是原型繼承 (Prototypal inheritance)而不是古典繼承 (Classical Inheritance),所以為了讓 JavaScript 回歸單純的原型繼承,現在的瀏覽器大部分都支援 Object.create() 這種單純的方式來建立物件。
後來也取得了胡立大大的回應,在這邊整理一下:
- 第一個問題,這樣也是物件導向
- 第二個問題,實作上應該會以 class 為主, 無論是傳統的繼承方式還是原型繼承,兩者都是物件導向,而無論在哪個程式語言,就是用 class 這個語法,所以覺得最普遍而且也最容易懂
也就是說,為了方便與其他人溝通,最好還是使用 class 會是最普遍的做法。
至於 Object.creat
的部分,如果搜尋的話應該會看到 Object.create(null)
,意思就是要產生一個「純粹的」物件,不繼承任何的函式,所以佔用的空間最少也很乾淨,例如說只是單純想存資料的話就會使用這個方法。
後來也找到關於 Object.create(null)
的詳細敘述與範例,Vue 裡面也有運用到哦。