1.原型鏈繼承(最簡(jiǎn)單的繼承)
function Parent () {
this.name = '小梁'
this.arr = [1]
}
function Sub() {}
Sub.prototype = new Parent()
var sub1 = new Sub()
var sub2 = new Sub()
sub1.name = '碳碳'
sub1.arr.push(22)
console.log(sub1.name) //碳碳
console.log(sub2.name) //小梁
console.log(sub1.arr) //[1,22]
console.log(sub2.arr) //[1,22]
說(shuō)明:
1.原型鏈繼承其實(shí)可以用一句話總結(jié):拿父類實(shí)例來(lái)充當(dāng)子類原型對(duì)象岂却;
2.上面這個(gè)例子可以這樣子理解:
*sub1.name = '碳碳':給sub1定義了一個(gè)name屬性值為‘碳碳’(在實(shí)例屬性中尋找name,找到了就改變?cè)搶?shí)例屬性的值瘪板,找不到就新建該屬性并進(jìn)行賦值)捂龄;
*sub1.arr.push(22):為實(shí)例sub1的arr數(shù)組添加一個(gè)元素淑仆,先在sub1的實(shí)例屬性中尋找名為arr的數(shù)組涝婉,沒(méi)有找到,沿著原型鏈往上找蔗怠,找到了arr數(shù)組墩弯,并對(duì)該數(shù)組進(jìn)行操作吩跋;因?yàn)閬?lái)自原型對(duì)象的引用屬性是所有實(shí)例共享的所以sub2.arr的值也跟著改變了;
*console.log(sub1.name):先在實(shí)例屬性中尋找name屬性渔工,之前/sub1.name = '碳碳'/操作為sub1實(shí)例創(chuàng)建了name屬性锌钮,所以在實(shí)例屬性中能夠找到name屬性,值為‘碳碳’引矩;
*console.log(sub2.name):先在實(shí)例屬性中尋找name屬性梁丘,找不到;沿著原型鏈往上找旺韭,找到了值為‘小梁’的name屬性兰吟。
3.優(yōu)點(diǎn):簡(jiǎn)單
4.缺點(diǎn):
4.1修改sub1.arr后sub2.arr也變了,因?yàn)閬?lái)自原型對(duì)象的引用屬性是所有實(shí)例共享的茂翔。
4.2創(chuàng)建子類實(shí)例時(shí)混蔼,無(wú)法向父類構(gòu)造函數(shù)傳參
2.借用構(gòu)造函數(shù)繼承
function Parent (value) {
this.value = value
this.arr = ['one']
this.fun = function () {
console.log('smile')
}
}
function Sub(value) {
Parent.call(this,value)
}
var sub1 = new Sub(1)
var sub2 = new Sub(2)
sub1.value = 4
sub1.arr.push('two')
console.log(sub1.value) //4
console.log(sub2.value) //2
console.log(sub1.arr) //["one", "two"]
console.log(sub2.arr) //["one"]
console.log(sub1.fun == sub2.fun) //false
說(shuō)明:
1.借父類的構(gòu)造函數(shù)來(lái)增強(qiáng)子類實(shí)例,等于是把父類的實(shí)例屬性復(fù)制了一份給子類實(shí)例裝上了
2.優(yōu)點(diǎn):
2.1解決了子類實(shí)例共享父類引用屬性的問(wèn)題;
2.2創(chuàng)建子類實(shí)例時(shí)珊燎,可以向父類構(gòu)造函數(shù)傳參;
3.缺點(diǎn):無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用惭嚣,每個(gè)子類實(shí)例都持有一個(gè)新的fun函數(shù),太多了就會(huì)影響性能悔政。
3.組合繼承(原型+構(gòu)造函數(shù))
function Parent (value) {
this.value = value
this.arr = ['one']
}
Parent.prototype.fun = function () {
return 'smile'
}
function Sub(value){
Parent.call(this,value)
}
Sub.prototype = new Parent()
var sub1 = new Sub(1)
var sub2 = new Sub(2)
console.log(sub1.value) //1
console.log(sub2.value) //2
console.log(sub1.fun == sub2.fun) //true
說(shuō)明:
1.把實(shí)例函數(shù)都放在原型對(duì)象上晚吞,以實(shí)現(xiàn)函數(shù)復(fù)用。同時(shí)還要保留借用構(gòu)造函數(shù)方式的優(yōu)點(diǎn)谋国,通過(guò)Parent.call(this,value)繼承父類的基本屬性和引用屬性并保留能傳參的優(yōu)點(diǎn)槽地;通過(guò)Sub.prototype = new Parent()繼承父類函數(shù),實(shí)現(xiàn)函數(shù)復(fù)用芦瘾;
2.優(yōu)點(diǎn):
不存在引用屬性共享問(wèn)題捌蚊;
可傳參;
函數(shù)可復(fù)用近弟;
3.缺點(diǎn)
子類原型上有一份多余的父類實(shí)例屬性缅糟,因?yàn)楦割悩?gòu)造函數(shù)被調(diào)用了兩次,生成了兩份祷愉,而子類實(shí)例上的那一份屏蔽了子類原型上的窗宦。。二鳄。又造成了內(nèi)存浪費(fèi):
例如:console.log(sub1)
4.原型繼承
function sheng(obj) { //生孩子函數(shù)
var F = function() {}
F.prototype = obj
return new F
}
function parent() {
this.value = 1;
this.arr = ['aaa']
}
var sub = sheng(new parent())
//增強(qiáng)
sub.name = 'xiaoliang'
console.log(sub.value) //1
console.log(sub.arr) //['aaa']
console.log(sub.name) //'xiaoliang'
console.log(sub)
說(shuō)明:
1.用生孩子函數(shù)得到得到一個(gè)“純潔”的新對(duì)象(“純潔”是因?yàn)闆](méi)有實(shí)例屬性)赴涵,再逐步增強(qiáng)之(填充實(shí)例屬性)
2.優(yōu)點(diǎn):從已有對(duì)象衍生新對(duì)象,不需要?jiǎng)?chuàng)建自定義類型订讼;
3.缺點(diǎn):
3.1原型引用屬性會(huì)被所有實(shí)例共享髓窜,因?yàn)槭怯谜麄€(gè)父類對(duì)象來(lái)充當(dāng)了子類原型對(duì)象,所以這個(gè)缺陷無(wú)可避免
3.2無(wú)法實(shí)現(xiàn)代碼復(fù)用
5.寄生式繼承
function sheng(obj) {
var F = function() {}
F.prototype = obj
return new F()
}
function parent() {
this.value = 1;
this.arr = ['aaa']
}
function creatSub(obj) {
var clone = sheng(obj)
//增強(qiáng)
clone.name = '小梁'
return clone
}
var sub = creatSub(new parent())
console.log(sub.name)
說(shuō)明:
1.其實(shí)覺(jué)得寄生式和原型式差別不大躯嫉,就是新增一個(gè)函數(shù)來(lái)進(jìn)行實(shí)例增強(qiáng)而已=纱烘。=。祈餐。
6.寄生組合繼承(最佳方式)
function Super(obj){
var F = function(){};
F.prototype = obj;
return new F();
}
function Parent(){
this.val = 1;
this.arr = [1];
}
Parent.prototype.fun1 = function(){};
Parent.prototype.fun2 = function(){};
function Sub(){
Parent.call(this); // 核心
}
var proto = Super(Parent.prototype); // 核心
proto.constructor = Sub; // 核心
Sub.prototype = proto; // 核心
var sub = new Sub();
console.log(sub.val)
console.log(sub.arr)
說(shuō)明:
1.寄生組合繼承應(yīng)該可以說(shuō)是相對(duì)比較完美的繼承的方式了擂啥!但是因?yàn)橛闷饋?lái)比較麻煩,所以所以組合繼承是依然是最常用的帆阳;