繼承
由於函數沒有簽名,因此在ECMAScript中只支持實現繼承,不支持接口繼承。
一.原型鏈
function SuperType){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subProperty = false;
}
SubType.prototype = new SuperType();//繼承
SubType.prototype.getSubValue = function(){
return this.subProperty;
};
var instance = new SubType();
alert(instance.getSuperValue());//true
alert(instance instanceof Object);//true
alert(instance instanceof SuperType);//true
alert(instance instanceof SubType);//true
alert(Object.prototype.isPrototypeOf(instance));//true;
alert(SuperType.prototype.isPrototypeOf(instance));//true;
alert(SubType.prototype.isPrototypeOf(instance));//true;
SubType繼承了SuperType,而繼承是通過創建SuperType實例,並將該實例賦值給SubType.prototype實現的,實現的本質是:重寫原型對象,代之以一個新(父)類型的實例。SubType的新原型首先是SuperType的實例,因此它具有SuperType所有的屬性和方法內部還有一個指向SuperType原型的指針,因爲property是一個SuperType的實例屬性,現在SubType.prototype是SuperType的一個實例因此現在property位於SubType.prototype中,而getSuperValue()是一個原型方法,因此還在SuperType.prototype中。
通過原型鏈實現繼承的情況下,搜索過程如下
1>搜索實例
2>搜索SubType.prototype
3>搜索SuperType.prototype
給原型添加方法(重寫或者添加方法)的代碼一定要放在替換原型的語句之後
原型鏈的問題
第一個問題:在通過原型實現繼承的時候,原型實際上變成了另一個類的實例,於是原先的實例屬性就變成了現在的原型屬性。
function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);
SuperType的每個實例都有colors屬性,SubType.prototype現在是SuperType的實例因此也有colors屬性,結果就是SubType的所有實例都會共享這個colors屬性。
第二個問題:在創建子類型的實例時,不能向超類的構造函數傳遞參數。
<pre name="code" class="javascript">二.借用構造函數
在子類的構造函數中調用超類的構造函數,函數只不過是在特定環境中執行代碼的對象。因此可以通過call或者apply來在新建的對象上執行構造函數。
function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);//red,blue,green,black
var instance2 = new SubType();
alert(intance2.colors);//red,blue,green
1.傳遞參數:在子類構造函數中向超類構造函數傳遞參數
function SuperType(name){
this.name = name;
}
function SubType(){
SuperType.call(this,"Nicho");
this.age = 29;
}
2.借用構造函數的問題:方法不可見
三.組合繼承
原型鏈實現對原型屬性和方法的繼承
借用構造函數實現對實例屬性的繼承
function SuperType(name){
this.name = name;
this.colors =["red","blue","green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name,age){
SuperType.call(this,name);
this.age =age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
alert(this.age);
};
四.原型式繼承:藉助原型可以基於已有的對象創建新對象,同時還不必因此創建自定義類型。
function object(o){
function F(){}
F.prototype = o;
return new F();
}