請記住,可以使用建構函式建立新物件,例如 new F()
。
如果 F.prototype
是物件,則 new
營運子會使用它為新物件設定 [[Prototype]]
。
JavaScript 從一開始就有原型繼承。它是該語言的核心功能之一。
但在過去,沒有辦法直接存取它。唯一可靠的方法是建構函式的 "prototype"
屬性,本章節會說明。因此,許多腳本仍然使用它。
請注意,這裡的 F.prototype
表示 F
上名為 "prototype"
的一般屬性。它聽起來與「原型」一詞類似,但這裡我們真正指的是具有此名稱的一般屬性。
以下是範例
let animal = {
eats: true
};
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype = animal;
let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
alert( rabbit.eats ); // true
設定 Rabbit.prototype = animal
實際上表示:「當建立 new Rabbit
時,將其 [[Prototype]]
指定為 animal
」。
以下是結果
在圖片中,"prototype"
是水平箭頭,表示一般屬性,而 [[Prototype]]
是垂直箭頭,表示 rabbit
從 animal
繼承。
F.prototype
僅在 new F
時使用F.prototype
屬性僅在呼叫 new F
時使用,它會指定新物件的 [[Prototype]]
。
如果在建立後,F.prototype
屬性變更(F.prototype = <另一個物件>
),則由 new F
建立的新物件將具有另一個物件作為 [[Prototype]]
,但現有物件會保留舊物件。
預設的 F.prototype、建構函式屬性
每個函式都有 "prototype"
屬性,即使我們沒有提供它。
預設的 "prototype"
是僅有一個屬性的物件,該屬性為 constructor
,指向函式本身。
如下所示
function Rabbit() {}
/* default prototype
Rabbit.prototype = { constructor: Rabbit };
*/
我們可以檢查它
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
alert( Rabbit.prototype.constructor == Rabbit ); // true
當然,如果我們什麼都不做,則所有兔子都可以透過 [[Prototype]]
使用 constructor
屬性
function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }
let rabbit = new Rabbit(); // inherits from {constructor: Rabbit}
alert(rabbit.constructor == Rabbit); // true (from prototype)
我們可以使用 constructor
屬性來使用與現有物件相同的建構函式建立新物件。
如下所示
function Rabbit(name) {
this.name = name;
alert(name);
}
let rabbit = new Rabbit("White Rabbit");
let rabbit2 = new rabbit.constructor("Black Rabbit");
當我們有一個物件,不知道哪個建構函式用於建立它(例如,它來自第三方程式庫),並且我們需要建立另一個相同類型的物件時,這很方便。
但 "constructor"
最重要的事情可能是...
...JavaScript 本身並未確保正確的 "constructor"
值。
是的,它存在於函式的預設 "prototype"
中,但僅此而已。之後發生什麼事 - 完全取決於我們。
特別是,如果我們將預設原型整體替換,則其中將沒有 "constructor"
。
例如
function Rabbit() {}
Rabbit.prototype = {
jumps: true
};
let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
因此,為了保留正確的 "constructor"
,我們可以選擇將屬性新增/移除到預設 "prototype"
,而不是將其整體覆寫
function Rabbit() {}
// Not overwrite Rabbit.prototype totally
// just add to it
Rabbit.prototype.jumps = true
// the default Rabbit.prototype.constructor is preserved
或者,手動重新建立 constructor
屬性
Rabbit.prototype = {
jumps: true,
constructor: Rabbit
};
// now constructor is also correct, because we added it
摘要
在本章中,我們簡要地描述了為通過建構函式建立的物件設定 [[Prototype]]
的方法。稍後我們將看到更多依賴它的進階程式設計模式。
一切都相當簡單,只需幾個註解就能讓事情清楚
F.prototype
屬性(不要將它誤認為[[Prototype]]
)在呼叫new F()
時設定新物件的[[Prototype]]
。F.prototype
的值應該是物件或null
:其他值將無法運作。"prototype"
屬性只有在設定在建構函式上,並使用new
呼叫時才有這種特殊效果。
在一般物件上,prototype
沒有什麼特別之處
let user = {
name: "John",
prototype: "Bla-bla" // no magic at all
};
預設所有函式都有 F.prototype = { constructor: F }
,因此我們可以透過存取物件的 "constructor"
屬性來取得物件的建構函式。
留言
<code>
標籤,若要插入多行程式碼,請將它們包覆在<pre>
標籤中,若要插入 10 行以上的程式碼,請使用沙盒 (plnkr、jsbin、codepen…)