# JavaScript的建構式(Constructor) ###### tags: `JavaScript` `Interview Preparation` :::warning :bulb: 本站筆記已同步更新到我的[個人網站](https://simplydevs.netlify.app/)囉! 歡迎參觀與閱讀,體驗不同的視覺感受! ::: [TOC] ## :memo: 什麼是建構式(Constructor) 建構式(Constructor)是一種在創造物件時,執行初始化的函式。使用`new`關鍵字時,參數(arguments)將被傳入Constructor函式。以下分別介紹傳統的constructor function,以及ES6引入的class中的`constructor`方法。 ### 物件建構函式 (The Object Constructor Function) 要使用constructor創造物件,只需定義一個帶有任意數量參數(arguments)的 JavaScript 函式即可。在函式內部,關鍵字`this`指的是正在創造的物件,因此我們可以用`this.property`來寫入該物件的屬性。**constructor函式的第一個字母最好使用大寫字母,以方便溝通、及避免與一般函式混淆**。 例如: ```javascript=1 // Define a constructor function function Food(name, cost, rating) { this.name = name; this.cost = cost; this.rating = rating; this.info = function(){ console.log(`The ${this.name} costs ${this.cost} dollars and has a rating of ${this.rating} stars.`) } } const cheese = new Food('cheese', 15, 4.5) console.log(cheese) /* output: create a new instance Food { name: 'cheese', cost: 15, rating: 4.5, info: [Function (anonymous)] } */ cheese.info() // output: The cheese costs 15 dollars and has a rating of 4.5 stars. ``` - 上述例子中,由constructor(也就是`Food`函式)所建立的物件稱為實例(Instance),因此,`cheese`是一個實例。也可以用`constructor.name`的方法取得該物件的constructor function名稱,例如上述例子中: ` console.log(cheese.constructor.name) // output: Food ` - `this`指向的是正在建立的物件,所以上述的constructor function如果寫成下面的程式碼,會得到一樣的結果: ```javascript= function Food(name, cost, rating) { this.name = name; this.cost = cost; this.rating = rating; this.info = function(){ console.log(`The ${this.name} costs ${this.cost} dollars and has a rating of ${this.rating} stars.`) } return this } const cheese = new Food('cheese', 15, 4.5) cheese.info() // output: The cheese costs 15 dollars and has a rating of 4.5 stars. ``` - 如果沒有使用`new`關鍵字,則不會創造新的物件,而只是單純執行constructor function,因此`this`不會指向新物件,而是指向全域物件(global object),也就是`window`,因此在上述的例子中,如果把程式碼改成: ```javascript= function Food(name, cost, rating) { this.name = name; this.cost = cost; this.rating = rating; this.info = function(){ console.log(`The ${this.name} costs ${this.cost} dollars and has a rating of ${this.rating} stars.`) } } // 拿掉new關鍵字 const cheese = Food('cheese', 15, 4.5) cheese.info() // output: undefined ``` 會得到`undefined`的結果以及以下error: `TypeError: Cannot read properties of undefined (reading 'info')` 因為此時的`this`指向的是全域物件`window`,`window`中沒有`info`這個屬性(property),因此結果是`undefined` ### 類別(Class)中的`constructor`方法 (The Class constructor Method) Class是ECMAScript 6 中引入的模板,一樣可以用來創造物件。Class中的constructor和傳統的constructor function類似,用來建立和初始化一個類別的物件,只需定義一個帶有任意數量參數(arguments)的 JavaScript 函式即可。在函式內部,關鍵字`this`指的是正在創造的物件。和傳統建構式的差別除了**更容易閱讀、減少與一般函式混淆之外,也可以將原型(prototype)的方法直接寫在class裡面。** 例如[MDN文件](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Classes/constructor)中的例子: ```javascript= class Polygon { constructor(height, width) { this.height = height; this.width = width; } // Getter get area() { return this.calcArea(); } // Method calcArea() { return this.height * this.width; } } const square = new Polygon(10, 10); console.log(square.area); //100 ``` 上述程式碼可以觀察到幾個重點: * `constructor`是class中一種特殊的方法(method),用來建立和初始化一個類別的物件。一個類別只能有一個名為`constructor`的特別方法,如果一個 class 出現兩次以上的 `constructor`,就會發生 `SyntaxError`。 * getter: 和物件實字 (Object Literals)一樣,可以用[`get`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)語法將物件屬性和函式綁定,查找該屬性時會呼叫該函式 * 方法(Method): 方法是定義在各類別實例的原型(prototype)上,並且所有的實例都擁有該方法,在console上觀察看看: ```javascript= // 同樣的constructor建立的instance擁有同樣的方法 const rectangle = new Polygon(20, 10) console.log(rectangle.calcArea()) // output: 200 // 兩個instance擁有相同prototype console.log(Object.getPrototypeOf(square) === Object.getPrototypeOf(rectangle)) // output: true ``` --- ## 參考資料 * [MDN文件](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Classes/constructor) * [W3Schools-JavaScript Object Constructors](https://www.w3schools.com/js/js_object_constructors.asp) * [[ES6 JavaScript] 類別 (Class) 與 建構式 (Constructor)](https://zwh.zone/es6-javascript--e9-a1-9e-e5-88-a5-class--e8-88-87--e5-bb-ba-e6-a7-8b-e5-bc-8f-constructor/) * [[筆記] 談談 JavaScript 中的 function constructor 和關鍵字 new](https://pjchender.blogspot.com/2016/06/javascriptfunction-constructornew.html) * [鐵人賽:JavaScript 建構式](https://www.casper.tw/javascript/2017/12/18/javascript-constructor/) * [建構物件範本:Constructor Function](https://javascript.alphacamp.co/constructor-function.html) * [[JavaScript] new的用法與基本概念](https://dotblogs.com.tw/AceLee/2017/06/22/135553) * [[JS] JavaScript 類別(Class)](https://pjchender.dev/javascript/js-class/#prototype-method%E5%8E%9F%E5%9E%8B%E6%96%B9%E6%B3%95) * [鐵人賽:ES6 建構式語法糖](https://www.casper.tw/javascript/2017/12/31/javascript-constructor/) ::: success :crescent_moon:  本站內容僅為個人學習記錄,如有錯誤歡迎留言告知、交流討論! :::