簡而言之:
new something2() instanceof something2 === false
與此相關的,如果你擴展你的榜樣使用原型屬性
Something.prototype.method = function() { };
something2.prototype.method = function() { };
你會發現,原型是不是在後一種情況下繼承:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
該rea l答案是你正在攻擊完全不同的基礎機器。調用new
調用[[Construct]]機制,該機制涉及根據構造函數的.prototype
屬性設置[[Prototype]]屬性。
但是一個有趣的事情發生在[[Construct]]算法的步驟8--10:設置一個新的空對象,然後附加其[[Prototype]]後,它會執行[[Call] ]到實際的構造函數,使用這個新的空加原型對象作爲this
。然後,在第9步中,如果事實證明該構造函數返回了一些東西 - 它拋棄了原型綁定,傳遞爲this
的對象,它一直花費在設置上!
注意:您可以訪問對象的[[原型](這是由不同構造的.prototype
)與Object.getPrototypeOf
:
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
回答一些元問題:
- 不,請不要大寫
something2
,因爲它是工廠函數而不是構造函數。如果某些東西是大寫的,則預計會有構造函數語義,例如new A() instanceof A
。
- 如果您擔心全局命名空間遭到破壞,您應該開始使用strict mode,將
"use strict";
放在文件的頂部。嚴格模式的很多很好的清理之一是this
默認爲undefined
,而不是全局對象,例如,在構造函數嘗試將屬性附加到undefined
時調用構造函數而不使用new
將導致錯誤。
- 工廠函數(又稱「閉包模式」)通常是構造函數和類的合理替代,只要您(a)不使用繼承; (b)不構造太多的對象實例。後者是因爲在閉包模式中,每個方法的新實例附加到每個新創建的對象,這對內存使用來說並不好。國際海事組織(IMO)最大的回報就是使用"private" variables(這是一個good thing,並且別讓別人告訴你:P)。
有點警惕先生克羅克福德。雖然他有很多好話要說,但他確實有不同意見。 – staticsan 2012-04-26 06:50:37