function-constructors-and-prototype
前一堂課介紹了如何透過關鍵字 new
來建立物件,這堂課將進一步介紹 function construsctors
和 .prototype
Prototype
延續上一堂課的範例,如果透過 new
關鍵字來建立的物件,並使用 __proto__
來查看它的 prototype
會是什麼呢 ?
1 | function Person(firstname, lastname) { |
我們會得到一個名為 Person
的空物件
但這到底是如何形成的呢 ?
之前的課程有提到過,在一個函式被件建立時,它會有幾個預設的屬性,函式內的程式碼 - code
、匿名函式不會有的 - name
和一個只被用來產生物件的 function constructor
才會有的屬性 - prototype
但這裡很弔詭的是,函式的 prototype
屬性並不是這個函式的 prototype
,而是透過 new
建立的物件的 __proto__
會自動指向這個函式的 prototype
屬性,這裡我們透過一個範例來了解
1 | function Person(firstname, lastname) { |
這裡我們將一個函式 getFullName
指派給 Person.prototype
,接著呼叫 john.getFUllName()
時,因為 john
本身並沒有這個方法,因此會沿著 prototypal chain
尋找,這時會找到 Person.prototype
,所以我們會得到 return
的結果。
那麼我們是不是也可以將這麼方法直接在函式 Person
建立時就賦予給它呢 ?
當然可以,因為透過 new
來建立物件時會呼叫這個函式,並將 this
指向新的空物件,就和屬性一樣,方法也會出現在新建立的物件中
1 | function Person(firstname, lastname) { |
記憶體占用
但這裡不一樣的是,如果把方法 getFullName
在函式建立時就賦予給它,每當我們透過 new
建立一個物件時,這些物件都會有自己的 getFullName
方法,所以自然會有各自占用的記憶體空間 ; 但如果透過 Person.prototype
賦予時,在呼叫物件的方法時,因為找不到,所以會沿著 prototypal chain
找到賦予在函式 prototype
的方法,藉此減少相同方法占用記憶體空間。
後續新增方法
透過函式的 prototype
新增方法的方式甚至可以在物件被建立後追加,不需要因為後續新增方法而去修改先前建立的物件
1 | function Person(firstname, lastname) { |
注意事項
在 JavaScript
透過 function constructor
的方式建立物件時,我們需要在呼叫函式前加上一個關鍵字 new
,但如果我們漏掉關鍵字 new
,整個程式碼還是可以執行的,只是這個變數會被賦予函式 return
的值,如果沒有回傳任何資料,這個值就會是 undefined
,因為這也是一般呼叫函式的方式
1 | function Person(firstname, lastname) { |
為了盡量避免發生這種錯誤,所以在開發時通常會一個慣例,那就是如果這個函式是一個 function constructor
,那命名上就會使用大寫開頭 capital letter
(person –> Person),藉此提醒我們在透過這類函式建立物件時,記得加上關鍵字 new
。