如果你從其他語言轉到javascript語言的開發,你會發現有很多讓你暈掉的術語,其中工廠函數(factory function)和構造函數(constructor function)就是其中的一個。本文試圖理順這兩者之間的區別.
Factory functions
工廠函數是將返回一個新的object的任何不是類或者構造函數的函數。在js中,任何函數都能夠返回一個object.如果我們不是通過new function()的方式來獲得這個對象的,那么她就是一個factory工廠函數.
function person(firstName, lastName, age) { const person = {}; person.firstName = firstName; person.lastName = lastName; person.age = age; return person; }
上面的js代碼會創建一個new object並且將傳入的參數賦值給到該object的屬性上,並且返回該new object.
Constructor functions
工廠函數和構造函數區別僅僅在於其用戶場景use case以及約定俗成的convention不同,基本上兩者是相似的。對於構造函數,人們慣例convention使用首字母大寫方式來表示這是一個constructor構造函數.構造函數往往其use case是需要需要通過 new 關鍵字調用返回類似對象的場景,並且隨后我們可以通過 instanceof 關鍵字來做實例類型檢查的場景。
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; }
通過new關鍵字來創建新的對象objects
如上面所說,工廠函數和構造函數基本上是一樣的,你現在估計有以下問題:
1. 我們可以對工廠函數來使用 new 關鍵字嗎?
2.如果針對工廠函數和構造函數,我們使用 new 關鍵字將會發生什么呢?
3. 如果針對構造函數並不使用 new 關鍵字去創造對象會怎么樣呢?
下面我們將試圖回答上面的幾個問題.
我們先使用new關鍵,應用到工廠函數和構造函數身上,並且console.log打印以下,看看有什么不同.
使用 new factory 函數
function person(firstName, lastName, age) { const person = {}; person.firstName = firstName; person.lastName = lastName; person.age = age; return person; } const mike = new person('mike', 'grand' 23);
使用constructor function
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } const mike = new Person('mike', 'grand', 23);
new操作符的背后
通過 new 構造函數方式創建object時有以下幾個過程發生:
function Person(firstName, lastName, age) { // this = {}; // this.__proto__ = Person.prototype; // Set up logic such that: if // there is a return statement // in the function body that // returns anything EXCEPT an // object, array, or function: // return this (the newly // constructed object) // instead of that item at // the return statement; this.firstName = firstName; this.lastName = lastName; this.age = age; // return this; }
上面的// 注釋行內容就是當使用new ConstructFunction()創建新對象時js引擎自動增加的部分偽代碼。
1.創建一個新的空object並且bind到this關鍵字
2.設置該對象的__proto__指向為構造函數的prototype.
3.增加以下邏輯:如果函數體中有return語句,但是返回的如果不是Object,array,或者function的話,則直接返回this指針
4.返回this object
我們把上面的邏輯增加到普通的函數體內,看看new factory調用時的結果:
function person(firstName, lastName, age) { // this = {}; // this.__proto__ = Person.prototype; // Set up logic such that: if // there is a return statement // in the function body that // returns anything EXCEPT an // object, array, or function: // return this (the newly // constructed object) // instead of that item at // the return statement; const person = {}; person.firstName = firstName; person.lastName = lastName; person.age = age; return person; // return this; }
我們看到由於person是一個object,因此return this就會被忽略,而是直接返回person對象。
如果使用構造函數時,忘記使用 new 關鍵字,會怎樣?
function Person(firstName, lastName, age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } const mike = new Person('mike', 'grand', 23); const bob = Person('bob', 'grand', 23);
我們可以看到bob為undefined,原因是Person函數本身並沒有返回任何內容,因此bob就為undefined.
但是我們會發現firstName,lastName和age這幾個屬性都被添加到了window全局對象上了。
https://medium.com/@chamikakasun/javascript-factory-functions-vs-constructor-functions-585919818afe