在 JavaScript 中除透過過物件實體語法 {} 來建立物件之外,
還可以透過在呼叫 function 前透過 new 運算子來建立物件,
new 運算子會將後方呼叫執行的 function 在執行脈絡中的 this 改為參考到新個空物件上,
並且在呼叫的 function 中的程式碼區塊裡透過 this 後的 .
運算子新增空物件的屬性或方法:
function Person(firstname, lastname) {
console.log(this);
this.firstname = firstname;
this.lastname = lastname;
console.log('This function is invoked.'); // 確認 function 有被執行過
}
var john = new Person('John', 'Doe');
console.log(john);
var jane = new Person('Jane', 'Doe');
console.log(jane);
透過開法者工具的 console 來確認是否像上述所說的一樣:
function 預設情況下如果沒有寫明回傳的內容時會回傳 undefined,
但在呼叫 function 前增加一個 new 運算子後這個 function 就變成建構子,
這會讓 function 回傳結果變成物件,
至於物件是否有值則要看是否有另外透過 this 與 prototype 來添加.
對於想要當成建構子運用的 function,
也要避免在 function 中回傳任何值,
就樣就失去在 function 前寫一個 new 運算子來把回傳值變成物件了,
另外 function 除了之前說兩個隱藏屬性(名稱屬性與程式屬性外)其實還有一個專屬給建構子用的屬性,
只在建構子創造完空物件後才能取用,
這個屬性就是 prototype 屬性,
當在呼叫 function 前加上 new 運算子後,
會把 function 的 prototype 屬性專屬給透過建構子創建出來的物件使用,
function 的 protype 屬性會被轉成原型物件並讓建構子創建出來的物件可以在原型鏈下找到並取用,
所以我可以這樣替透過建構子產生的物件新增方法:
function Person(firstname, lastname) {
console.log(this);
this.firstname = firstname;
this.lastname = lastname;
console.log('This function is invoked.');
}
Person.prototype.getFullName = function() {
return this.firstname + ' ' + this.lastname;
}
var john = new Person('John', 'Doe');
console.log(john);
var jane = new Person('Jane', 'Doe');
console.log(jane);
Person.prototype.getFormalFullName = function() {
return this.lastname + ', ' + this.firstname;
}
// 當直接在 john 物件上透過 `.` 運算子取用 getFormalFullName 方法時,
// 會到 john 物件的原型鏈下去找有 getFormalFullName 方法的原型物件來取用
console.log(john.getFormalFullName());
之所以沒有像在 Proson function 中直接透過 this 與 .
運算子來添加 firstname, lastname 屬性一樣,
透過 this 與 .
運算子來添加方法是因為透過 this 來添加的屬性或方法會在記憶體中占用空間,
如果透過建構子新增 100 個物件就會有 100 個記憶體位址的消耗,
如果使用建構子的 .prototype 屬性來參考到要使用的方法則只會有 1 個記憶體位址的消耗,
這樣可以減少記憶體空間的使用量來提升程式碼效能.