先寫一個(gè)父級(jí)的構(gòu)造函數(shù)
function Parent(name){
this.name = name;
this.money = 10000000;
this.hobby = function(){
console.log("Parent this.hobby");
}
}
Parent.prototype.active = function(){
console.log("Parent.prototype");
}
Parent.prototype.eat = function(){
console.log("Parent.prototype.eat");
}
接著子集的構(gòu)造方法
function Son(name){
}
子集想要繼承父級(jí)里面的內(nèi)容就要在里面加上
function Son(name){
Parent.call(this,name);
}
這樣就可以繼承父級(jí)里面的內(nèi)容
var newSon = new Son("rrrr");
console.log(newSon.name); // rrrr
console.log(newSon.money); // 10000000
newSon.hobby(); // Parent this.hobby
這樣寫看似沒什么問(wèn)題鲸拥,但是當(dāng)我們?cè)谧蛹锩鎸懮吓c父級(jí)相同的屬性或者方法呢?
function Son(name){
Parent.call(this,name); // rrrr
this.money = 10;
this.hobby = function(){
console.log("Son this.hobby");
}
}
var newSon = new Son("rrrr");
console.log(newSon.name); // rrrr
console.log(newSon.money); // 10
newSon.hobby(); // Son this.hobby
上述代碼表明,子集繼承父級(jí)呐舔,在自身重寫該方法的時(shí)候以自身為準(zhǔn)
回到上述繼承 構(gòu)造繼承
function Parent(name){
//屬性
this.name = name;
this.money = 10000000
//實(shí)例方法
this.hobby = function(){
console.log("Parent this.hobby");
}
}
//原型方法
Parent.prototype.active = function(){
console.log("Parent.prototype");
}
Parent.prototype.eat = function(){
console.log("Parent.prototype.eat");
}
function Son(name){
Parent.call(this,name);
}
var newSon = new Son("rrrr");
console.log(newSon.name); // rrrr
console.log(newSon.money); // 100000
console.log(newSon instanceof Parent); // false
console.log(newSon instanceof Son); // true
newSon.hobby() // Parent this.hobby
newSon.active(); // 報(bào)錯(cuò)
newSon.eat(); // 報(bào)錯(cuò)
由上述可知贴唇,子集繼承父級(jí),只繼承父級(jí)本身的屬性和方法摔踱,不會(huì)繼承父級(jí)原型上的方法抓谴,因?yàn)闃?gòu)造繼承的核心就是使用父類的構(gòu)造函數(shù)來(lái)增強(qiáng)子類的實(shí)例,等于是復(fù)制父類的實(shí)例屬性給子類(沒用到原型)
特點(diǎn):
- 解決子類實(shí)例共享父類引用屬性的問(wèn)題
- 創(chuàng)建子類實(shí)例時(shí)寞缝,可以向父類傳參數(shù)
- 可以實(shí)現(xiàn)多繼承癌压,(call多個(gè)父類對(duì)象)
缺點(diǎn): - 實(shí)例并不是父類的實(shí)例,只是子類的實(shí)例
- 只能繼承父類的實(shí)例屬性和方法荆陆,不能繼承原型屬性和方法
- 無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用滩届,每個(gè)子類都有父類實(shí)力函數(shù)的副本,影響性能
這就可以利用到 實(shí)例繼承
function Son(name){
var ins = new Parent(name);
return ins;
}
var newSon = new Son("ggg");
console.log(newSon.name); // ggg
console.log(newSon.money); // 10000000
console.log(newSon instanceof Parent); // true
console.log(newSon instanceof Son); // false
newSon.hobby() // Parent this.hobby
newSon.active(); // Parent.prototype
newSon.eat(); // Parent.prototype.eat
實(shí)例繼承的核心被啼。為父類實(shí)例添加新特性帜消,作為子類實(shí)例返回
特點(diǎn):
- 不限制調(diào)用方式,不管是 new 子類() 還是 子類() 浓体,返回的對(duì)象具有相同的效果
缺點(diǎn): - 實(shí)例是父級(jí)的實(shí)例泡挺,不是子類的實(shí)例
- 不支持多繼承
再有 組合繼承
function Son(name){
Parent.call(this,name);
}
Son.prototype.eat = function(){
console.log("Son.prototype.eat");
}
Son.prototype = new Parent();
var newSon = new Son("ggg");
console.log(newSon.name); // ggg
console.log(newSon.money); // 10000000
console.log(newSon instanceof Parent); // true
console.log(newSon instanceof Son); // true
newSon.hobby() // Parent this.hobby
newSon.active(); // Parent.prototype
newSon.eat(); // Parent.prototype.eat
組合繼承的核心是通過(guò)父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點(diǎn)命浴,然后通過(guò)降幅及實(shí)例子類原型娄猫,實(shí)現(xiàn)函數(shù)復(fù)用
特點(diǎn):
- 可以繼承實(shí)例屬性贱除、方法,也可以繼承原型屬性媳溺、方法
- 即是子類的實(shí)例月幌,也是父類的實(shí)例
- 不存在引用屬性共享問(wèn)題
- 可傳參
- 函數(shù)可復(fù)用
缺點(diǎn): - 調(diào)用了兩次父類構(gòu)造函數(shù),生成兩份實(shí)例(父類實(shí)例將子類原型上的那份屏蔽了)悬蔽,
最后寄生組合繼承扯躺,通過(guò)創(chuàng)建一個(gè)空的構(gòu)造函數(shù)。
function Son(name){
Parent.call(this,name);
}
Son.prototype.eat = function(){
console.log("Son.prototype.eat");
}
//創(chuàng)建一個(gè)空的構(gòu)造函數(shù)
function Link(){}
//將Person4 里面的構(gòu)造函數(shù)的原型 傳址賦值 到 Link構(gòu)造函數(shù)的原型里面
Link.prototype = Parent.prototype;
//實(shí)例化Student的構(gòu)造方法的原型蝎困。此時(shí) 實(shí)例化的時(shí)候會(huì)重新創(chuàng)建一個(gè)新的地址存儲(chǔ)录语,所以改變
//Student里面的方法的時(shí)候 不會(huì)影響Link 當(dāng)然 也不會(huì)影響Person4
Son.prototype = new Link();
var newSon = new Son("tt")
console.log(newSon.name); // tt
console.log(newSon.money); // 10000000
console.log(newSon instanceof Parent); // true
console.log(newSon instanceof Son); // true
newSon.hobby() // Parent this.hobby
newSon.active(); // Parent.prototype
newSon.eat(); // Parent.prototype.eat