[英]JavaScript prototype and call()
我正在學習js原型,並且想知道以下兩個部分之間是否有任何區別?
細分1:
function SuperType(){
this.color=["blue","yellow"];
}
function SubType(){
}
Subtype.prototype = new SuperType();
細分2 :
function SuperType(){
this.color=["blue","yellow"];
}
function SubType(){
SuperType.call(this);
}
並且如果以上兩個功能做的相同,那么為什么有些代碼會麻煩這樣做:
function SubType(){
SuperType.call(this);
}
SubType.prototype=new SuperType();
是的,有差異。
在段1中,子類SubType
不會調用SuperType
的構造函數,因此它永遠不會執行。 段1不是從另一個對象繼承的正確通用方法。
在段2中,子類SubType
確實調用了SuperType
的構造函數,因此語句this.color=["blue","yellow"];
被執行,但是原型設置不當,因此不會繼承SuperType
可能擁有的任何原型項。 段2不是從另一個對象繼承的正確通用方法。
如果SuperType
構造函數中沒有代碼,則段1將正常工作(在您的示例中不是這種情況)。 如您所示,由於未調用SuperType()
構造函數,因此this.color
僅在原型中,因此所有實例將共享同一數組,這通常不是您想要的。 正確調用構造函數將為每個實例提供this.color
的自己副本,而不是共享副本。
如果沒有向SuperType
原型添加任何內容並且沒有SuperType
構造函數參數,則第2部分將正常工作(在您的示例中可能是這種情況,但不是很好的常規做法)。
通用的工作方式也不是。
最后一個選擇是正確的通用處理方式,因為它既從原型繼承,又執行繼承對象的構造函數。
最通用的方法還使用.apply(this, arguments)
這樣將任何構造函數參數傳遞給繼承的對象.apply(this, arguments)
並初始化其自己的原型並設置其構造函數屬性。
// define base object constructor
function SuperType(){
this.color=["blue","yellow"];
}
// define base object methods on the prototype
SuperType.prototype.foo = function() {};
// ---------------------------------------------------------------------------
// define object that wants to inherit from the SuperType object
function SubType() {
// call base object constructor with all arguments that might have been passed
SuperType.apply(this, arguments);
}
// set prototype for this object to point to base object
// so we inherit any items set on the base object's prototype
SubType.prototype = new SuperType();
// reset constructor to point to this object not to SuperType
SubType.prototype.constructor = SubType;
// define any methods of this object by adding them to the prototype
SubType.prototype.myMethod = function() {};
如果您只支持IE9及更高版本,則應更改以下行:
SubType.prototype = new SuperType();
對此:
SubType.prototype = Object.create(SuperType.prototype);
這避免了為了獲得用於原型的對象而調用SuperType()
構造函數。 在大多數情況下,這確實無關緊要,但是在構造函數具有僅初始化其自身屬性之外的副作用的情況下,這很重要。
在第1部分中,原型已正確設置,但從未調用SuperType
的構造函數。
在第2段的開頭,將調用SuperType
的構造函數,但未設置原型。
最后一個示例是正確的,因為它可以正確設置原型並調用SuperType
的構造函數。
function SuperType() {
// Do some stuff.
}
function SubType() {
SuperType.apply(this, arguments);
}
SubType.prototype = new SuperType();
你不應該設置原型繼承
SubType.prototype=new SuperType ();
因為可能會有問題。
如果您這樣做,SubType的原型也將繼承屬性color作為SubType原型的自己的屬性,因為構造器已完成工作。 然后,每個subType的新實例都具有對原型中color屬性的引用,而不是實例本身的自身屬性,這最終不是您想要的,因為您只想繼承原型。 幸運的是,在調用超級構造函數之后,每個實例都獲得了自己的color屬性,但是color屬性仍然在原型中也定義了。 沒有必要
因此,要真正只繼承原型,您應該使用Object.create或執行類似的解決方法。
function SuperType()
{
if (SuperType.doNotConstruct) return;
this.color=["blue","yellow"];
}
function SubType()
{
SuperType.call (this);
}
SuperType.doNotConstruct=true;
SubType.prototype = new SuperType();
SuperType.doNotConstruct=false;
SubType.prototype.constructor=SubType;
第二種方法-更好的方法-因為不需要if構造函數中的Statement
function SuperType()
{
this.color=["blue","yellow"];
}
function SubType()
{
SuperType.call (this);
}
var CLASS=function () {}
CLASS.prototype=SuperType.prototype;
SubType.prototype=new CLASS ();
SubType.prototype.constructor=SubType;
@blake嘗試以下操作-當人們忘記調用超級構造函數並使用... prototype = new構造函數進行繼承時,這將顯示一個問題
function SuperType()
{
this.color=["blue","yellow"];
}
SuperType.prototype.addColor=function (name)
{
this.color.push ("red");
}
function SubType () {}
SubType.prototype=new SuperType ();
var a=new SubType ();
var b=new SubType ();
a.addColor ("red");
console.log (a.color);
console.log (b.color);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.