Object(物件):基礎知識 構造器和操作符 "new"
構造器和操作符 "new"
常規的 {...} 語法允許建立一個物件。但是我們經常需要建立許多類似的物件,例如多個使用者或選單項等。
這可以使用建構函式和 "new" 操作符來實現。
建構函式
建構函式在技術上是常規函式。不過有兩個約定:
它們的命名以大寫字母開頭。
它們只能由 "new" 操作符來執行。
例如:
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
當一個函式被使用 new 操作符執行時,它按照以下步驟:
一個新的空物件被建立並分配給 this。
函式體執行。通常它會修改 this,為其新增新的屬性。
返回 this 的值。
換句話說,new User(...) 做的就是類似的事情:
function User(name) {
// this = {};(隱式建立)
// 新增屬性到 this
this.name = name;
this.isAdmin = false;
// return this;(隱式返回)
}
所以 new User("Jack") 的結果是相同的物件:
let user = {
name: "Jack",
isAdmin: false
};
現在,如果我們想建立其他使用者,我們可以呼叫 new User("Ann"),new User("Alice") 等。比每次都使用字面量建立要短得多,而且更易於閱讀。
這是構造器的主要目的 —— 實現可重用的物件建立程式碼。
讓我們再強調一遍 —— 從技術上講,任何函式(除了箭頭函式,它沒有自己的 this)都可以用作構造器。即可以通過 new 來執行,它會執行上面的演算法。“首字母大寫”是一個共同的約定,以明確表示一個函式將被使用 new 來執行。
new function() { … }
如果我們有許多行用於建立單個複雜物件的程式碼,我們可以將它們封裝在一個立即呼叫的建構函式中,像這樣:
let user = new function() {
this.name = "John";
this.isAdmin = false;
// ……用於使用者建立的其他程式碼
// 也許是複雜的邏輯和語句
// 區域性變數等
};
這個建構函式不能被再次呼叫,因為它不儲存在任何地方,只是被建立和呼叫。因此,這個技巧旨在封裝構建單個物件的程式碼,而無需將來重用。
構造器的 return
通常,構造器沒有 return 語句。它們的任務是將所有必要的東西寫入 this,並自動轉換為結果。
但是,如果這有一個 return 語句,那麼規則就簡單了:
如果 return 返回的是一個物件,則返回這個物件,而不是 this。
如果 return 返回的是一個原始型別,則忽略。
換句話說,帶有物件的 return 返回該物件,在所有其他情況下返回 this。
例如,這裡 return 通過返回一個物件覆蓋 this:
function BigUser() {
this.name = "John";
return { name: "Godzilla" }; // <-- 返回這個物件
}
alert( new BigUser().name ); // Godzilla,得到了那個物件
這裡有一個 return 為空的例子(或者我們可以在它之後放置一個原始型別,沒有什麼影響):
function SmallUser() {
this.name = "John";
return; // <-- 返回 this
}
alert( new SmallUser().name ); // John
通常構造器沒有 return 語句。這裡我們主要為了完整性而提及返回物件的特殊行為。
省略括號
順便說一下,如果沒有引數,我們可以省略 new 後的括號:
let user = new User; // <-- 沒有引數
// 等同於
let user = new User();
這裡省略括號不被認為是一種“好風格”,但是規範允許使用該語法。
構造器中的方法
使用建構函式來建立物件會帶來很大的靈活性。建構函式可能有一些引數,這些引數定義瞭如何構造物件以及要放入什麼。
當然,我們不僅可以將屬性新增到 this 中,還可以新增方法。
例如,下面的 new User(name) 用給定的 name 和方法 sayHi 建立了一個物件:
function User(name) {
this.name = name;
this.sayHi = function() {
alert( "My name is: " + this.name );
};
}
let john = new User("John");
john.sayHi(); // My name is: John
/*
john = {
name: "John",
sayHi: function() { ... }
}
*/
類 是用於建立複雜物件的一個更高階的語法,我們稍後會講到。
總結
建構函式,或簡稱構造器,就是常規函式,但大家對於構造器有個共同的約定,就是其命名首字母要大寫。
建構函式只能使用 new 來呼叫。這樣的呼叫意味著在開始時建立了空的 this,並在最後返回填充了值的 this。
我們可以使用建構函式來建立多個類似的物件。
JavaScript 為許多內建的物件提供了建構函式:比如日期 Date、集合 Set 以及其他我們計劃學習的內容。