iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
Modern Web

JavaScript 之路,往前邁進吧!系列 第 5

JS之路 Day05 - Constructor Function(構造函式)

  • 分享至 

  • xImage
  •  

前言

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"),除了更好閱讀之外,也可以少寫許多東西,讓整個程式變得乾淨許多。

這種寫一次就可以反覆使用,就是構造函式的精髓所在,大家也多使用構造函式來優化自己的程式碼吧。

reference

[1] MDN - constructor
[2] Constructor, operator "new"
[3] MDN - new operator
[4] JS 对象机制深剖——new 运算符


上一篇
JS之路 Day04 - Prototypal Inheritance(原型繼承)
下一篇
JS之路 Day06 - 語法糖Class(上)
系列文
JavaScript 之路,往前邁進吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言