[英]Factory functions prototype
學習構造函數我提出了這個問題:
為什么不使用返回 object 而不是構造函數的普通函數?
讀了一下,我發現了工廠函數(ff)。 與構造函數的區別是:
this
替換 object 文字{ }
,new
return
的object。但我相信這還不夠簡化,它只是有點整潔,但不多。
舉個例子:
function box(x,y,z){
return {
x:x , y:y , z:z ,
volume: function (){return x*y*z}
}
}
我們可以很容易地編寫一個具有相同 function 的構造函數。
現在,我知道其中一個差異可能是原型。 所以這是我的問題:
與 function 一起創建的原型 object 確實有所作為。 當您使用new
調用 function 時, this
object 將得到該原型 object 作為其原型。 因此,新 object 的原型鏈比工廠 function 的原型鏈長了一步。
該語言提供了instanceof
運算符和constructor
屬性,這在您使用構造函數時很有用,因為它們提供了有關實例構造函數的信息。 對於 object 文字(在您的box
函數中使用),它確定構造函數是Object
而不是box
。
為了使兩個版本的函數更接近一點,以便僅突出顯示本質上的區別,您可以將它們編寫如下:
function box(x,y,z) {
let obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
// Better reference the properties here, ...in case they are changed:
obj.volume = function () { return obj.x * obj.y * obj.z }
return obj;
}
構造函數可能如下所示:
function Box(x,y,z) {
// `this` is already initialised as a new object with a specific prototype
this.x = x;
this.y = y;
this.z = z;
this.volume = function () { return this.x * this.y * this.z }
// `this` is returned by default, so no `return` is needed
}
注意原型鏈(運行代碼片段)和instanceof
的用處的區別:
function box(x,y,z) { let obj = {}; obj.x = x; obj.y = y; obj.z = z; obj.volume = function () { return obj.x * obj.y * obj.z } return obj; } function Box(x,y,z) { this.x = x; this.y = y; this.z = z; this.volume = function () { return this.x * this.y * this.z } } let a = box(1,2,3); let b = new Box(1,2,3); // Print prototype chains console.log("a-->" + Object.getPrototypeOf(a).constructor.name); let protB = Object.getPrototypeOf(b); console.log("b-->" + protB.constructor.name + "-->" + Object.getPrototypeOf(protB).constructor.name); // Print use of `instanceOf` console.log("a instanceof box?", a instanceof box); console.log("b instanceof Box?", b instanceof Box);
到目前為止,我忽略了一個事實,即volume
function 可以重復使用,而不是為每個實例單獨定義。 在這兩種情況下,您都可以將volume
function 定義為(更多)全局 function。 請注意,您現在可以使用this
關鍵字,因為通常您會將volume
稱為instance.volume()
:
function volume { return this.x * this.y * this.z }
function box(x,y,z) {
let obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
obj.volume = volume;
return obj;
}
盡管如此,您仍然有明確的obj.volume = volume
分配。 在構造函數模式中,您不需要創建該實例屬性。 在原型 object 上定義方法就足夠了:
function Box(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
// No need here to define `volume`
}
Box.prototype.volume = function { return this.x * this.y * this.z };
所以,實際上你只有一個對該方法的引用。
最后,還有class
語法,這是使用構造函數的替代方法:
class Box(x,y,z) {
constructor(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
}
volume() {
return this.x * this.y * this.z;
}
}
在這個語法中, volume
也是在原型上定義的,而不是在實例上。
到目前為止,比較有利於使用構造函數(在我看來)。
但:
this
object。 使用this
可能會令人困惑(正如 Stack Overflow 上關於該主題的許多問題所展示的那樣)。 一些程序員認為這是放棄構造函數的好理由。Animal
的Being
,從哪個Mammal
派生,從哪個...等等等等,可能會讓人感到困惑。 一個扁平的數據結構可以讓人感到如釋重負。是的,原型是所謂的工廠函數和構造函數之間的區別。
在您提供的示例代碼中,您將無法訪問box
的原型,即使添加了該原型也是如此。 當您使用new
關鍵字調用 function 時,它在內部執行的第一項工作是創建 object 並根據您通過box.prototype
提供的引用創建其原型鏈,並且在設置完該過程后,該過程將返回 ZA8CFDE6331BD59EB66ZC94 . 但在您的代碼中,訪問權限僅限於您返回的 object,它將覆蓋最初創建的 object 的返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.