JS之路 Day05 - Constructor Function(構造函式)
前言
Constructor Function
也是Function
,那它跟一般的Function
差在哪裡,有什麼特別之處,就是今天主要介紹的部分。
構造函式
剛剛有提到其實跟Function
差不多,所以正常來說為了要區分這兩者的差別,構造函式在命名上都會以大寫字母來寫,而構造函式的誕生,是要經過一個叫做new
這個關鍵字來創立。
意味著,使用new
來生成的函式就是構造函式。
沒有使用new
來生成,可以直接呼叫執行的,就是普通函式。
那什麼是new
?
new
關鍵字
new
這個關鍵字其實是new operator
,在 mdn 的解釋是:
The new operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function.
我自己翻起來是:new
可以創建一個定義物件類型,或者是具有構造函式的內置物件類型,它們的實例。
我的理解是new
只可以拿來創造構造函式,沒有用new
來創造就只會是普通函式。
接下來就來證明這件事情。
new
從原理下手
圖片來源:MDN
假如有個程式如下:
1 | const Food = function (fruit, color) { |
很明顯,我們後來可以創一個變數,使用new
的方式把 apple 跟 red 的資訊,傳遞給上面構造函式,就可以成功創造一個實例。
照著 MDN 上面的解釋,一步步來解析 new 幫忙做了什麼事情:
首先一開始 new 會幫忙創造一個空的物件,可以當作是{}。
然後把 {} 的 __proto__
指向 Food 的 prototype,這邊就是前幾篇講過的原型概念,這樣的方式是為了要繼承原型鏈。
接著下一步是呼叫這個構造函式,綁定{}是 this 的 context,
可以理解成 this 就會指向這個空物件,構造函式裡面的 this 是什麼,這裡就會是什麼 => this={}。
所以在這個例子來看,現在這個 context 裡面就會有兩個新的屬性。
最後那個一開始創建出來的物件,就會自動回傳,回傳一個有兩個屬性的物件,這就會是new Food("apple", "red")
最後結果,它將會儲存在apple
這個變數裡面。
以上就是new
會在背後幫忙做的事情。
有一個蠻好理解的方式,我從這邊看來的 https://javascript.info/constructor-new。
先看這個程式:
1 | function User(name) { |
這裡的 new User(...)
可以理解成這樣運行:
1 | function User(name) { |
所以最後返回的結果都是相同的物件:
1 | let user = { |
另外,從這裡還可以衍生一件事情,上面有提到說,在創造new
時就已經把所有重要的東西都放入 this 裡面,所以不會需要再return
回傳結果,所以在這裡可以再做一個劃分:
- 普通函式會使用
return
- 構造函式不會使用
return
什麼情況不能用new
?
不是 function 的時候:
我個人測試沒有 function 就會拋出異常:
1 | var Apple = {}; |
Apple is not a constructor,我明明已經弄成物件了,卻還是不行,那假如用 function:
1 | var Apple = function () {}; |
改成用 function 就不會報錯。
我的理解是,空的也不會報錯,基本上全部的函式都可以當作構造函式來使用,除了箭頭函式之外(它沒有 this),除此之外,都可以通過用 new 的方式來變成構造函式。
總結
語法的產生都有其原因的存在,而構造函式的產生是來自於有許多情境會需要創造很多相似的物件。
在創造其他物件時,只需要 new ABC(“abc”),除了更好閱讀之外,也可以少寫許多東西,讓整個程式變得乾淨許多。
這種寫一次就可以反覆使用,就是構造函式的精髓所在,大家也多使用構造函式來優化自己的程式碼吧。
reference
[1] MDN - constructor
[2] Constructor, operator “new”
[3] MDN - new operator
[4] JS 对象机制深剖——new 运算符