在javascript裏面看到javascript的繼承模式和傳統的繼承模式是有區別的,就想查資料看一下到底有區別,就看到了這篇文章,以爲講得還能夠,暫時先放上來,之後有別的東西再補充:
http://segmentfault.com/a/1190000000766541javascript
var Parent = function(){
this.name = 'parent';
};
Parent.prototype.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(){
this.name = 'child';
}
Child.protytype = new Parent();
var parent = new Parent();
var child = new Child();
console.log(parent.getName());//parent
console.log(child.getName());//child
這種事最簡單實現原型繼承的方法,直接把父類的對象複製給子類的構造函數的原型,這樣子類的對象就能夠訪問到父類以及父類構造函數的protytype
這種方法的優勢就是實現起來比較簡單,不須要任何特殊的操做;同時他的缺點也很明顯,若是子類須要作跟父類構造函數中相同的初始化動做,那麼就得在子類構造函數中再重複一遍父類中的操做:php
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototype.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(name) {
this.name = name || 'child';
};
Child.prototype = new Parent();
var parent = new Parent('myParent');
var child = new Child('myChild');
console.log(parent.getName());//myParent
console.log(child.getName());//myChild
上述還只是初始化name
屬性,若是初始化工做不斷增長,這種方式也不是很方便。java
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototype.getName = function(){
return this.name;
}
Parent.prototype.obj = {a:1};
var Child = function(name){
Parent.apply(this,arguments);
}
Child.prototype = new Parent();
var parent = new Parent('myParent');
var child = new Child('myChild');
console.log(parent.getNmae());//myParent
console.log(child.getName());//myChild
上面這種方法在子類構造函數中經過apply
調用父類的構造函數進行相同的的初始化工做,這樣無論負累作了多少初始化工做,子類能夠執行一樣的初始化工做。可是上面這種實現方法存在一個問題,父類構造函數被執行了兩次,一次是在子類構造函數中,椅子是在賦值子類原型的時候,這是多餘的,咱們能夠作如下改進:web
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototypr.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(name){
Parent.apply(this,arguments);
};
Child.protytype = Parent.protytype;
var parent = new Parent('myParent')
var child = new Child('myChild');
console.log(parent.getName());//myParent
console.log(child.getName());//myChild
這樣咱們只須要在子類構造函數中執行一次父類的構造函數,同時又能夠繼承父類原型中的屬性,這也比較原型的初衷,就是吧須要複用的內容放在原型中,咱們能夠繼承原型中可複用的內容
segmentfault
上面借用構造函數模式仍是存在問題,它把父類的原型直接賦值給子類的原型,這會形成一個問題,就是若是對子類的原型作了修改,那麼這個修改同時也會影響到父類的原型,進而影響父類對象。app
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototype.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(name){
Parent.apply(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
var parent = new Parent('myParent');
var child = new Child('myChild');
console.log(parent.getName());//myParent
console.log(child.getName());/myChild
這樣作事在子類原型和父類原型之間加入一個臨時的構造函數F
,切斷了子類原型和父類原型之間的聯繫,這樣子類原型的修改就不會影響到父類原型。svg
上面能夠刻到的咱們在Parent的prototype
屬性中加入一個obj
對象字面量屬性,可是一直沒有使用函數
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototype.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(name){
Parent.aplly(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
var parent = new Parent('myParent');
var child = new Child('myChild');
console.log(child.obj.a);//1
console.log(parent.obj.a);//1
child.obj.a = 2;
console.log(child.obj.a);//2
console.log(parent.obj.a);//2
在上面這種狀況,當咱們把child
對象obj.a
修改的時候,同時父類的原型中的obj.a
也會被修改。緣由是由於當訪問child.obj.a
的時候,咱們會沿着原型鏈一直找到父類的prototype
中,而後找到了obj
屬性,而後對obj.a
進行修改.this
var Parent = function(name){
this.name = name || 'parent';
};
Parent.prototype.getName = function(){
return this.name;
};
Parent.prototype.obj = {a:1};
var Child = function(name){
Parent.aplly(this,arguments);
};
var F = new function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
var parent = new Parent('myParent');
var child = new Child('myChild');
console.log(child.obj.a);//1
console.log(parent.obj.a);//1
child.obj.a = 2;
console.log(child.obj.a);//2
console.log(parent.obj.a);//2