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
假如有個程式如下:
const Food = function (fruit, color) {
this.fruit = fruit;
this.color = color;
};
const apple = new Food("apple", "red");
console.log(apple);
// Food { fruit: 'apple', color: 'red' }
很明顯,我們後來可以創一個變數,使用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。
先看這個程式:
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
這裡的 new User(...)
可以理解成這樣運行:
function User(name) {
// this = {};(隱式創建)
// 添加屬性到 this
this.name = name;
this.isAdmin = false;
// return this;(隱式返回)
}
所以最後返回的結果都是相同的物件:
let user = {
name: "Jack",
isAdmin: false
};
另外,從這裡還可以衍生一件事情,上面有提到說,在創造new
時就已經把所有重要的東西都放入this裡面,所以不會需要再return
回傳結果,所以在這裡可以再做一個劃分:
return
return
new
?不是function的時候:
我個人測試沒有function就會拋出異常:
var Apple = {};
var newApple = new Apple();
console.log(newApple);
//TypeError: Apple is not a constructor
Apple is not a constructor,我明明已經弄成物件了,卻還是不行,那假如用function:
var Apple = function () {};
var newApple = new Apple();
console.log(newApple);
//Apple {}
改成用function就不會報錯。
我的理解是,空的也不會報錯,基本上全部的函式都可以當作構造函式來使用,除了箭頭函式之外(它沒有this),除此之外,都可以通過用new的方式來變成構造函式。
語法的產生都有其原因的存在,而構造函式的產生是來自於有許多情境會需要創造很多相似的物件。
在創造其他物件時,只需要new ABC("abc"),除了更好閱讀之外,也可以少寫許多東西,讓整個程式變得乾淨許多。
這種寫一次就可以反覆使用,就是構造函式的精髓所在,大家也多使用構造函式來優化自己的程式碼吧。
[1] MDN - constructor
[2] Constructor, operator "new"
[3] MDN - new operator
[4] JS 对象机制深剖——new 运算符