講解前需要明白的幾點(diǎn)
- Javascript繼承:繼承機(jī)制并沒有明確規(guī)定,完全由開發(fā)者決定最合適的繼承方式
- 類的原型對(duì)象上的所有屬性和方法都會(huì)被子類擁有
- this關(guān)鍵字:誰(shuí)調(diào)用這個(gè)屬性和方法this就指誰(shuí)
1. 對(duì)象冒充方式實(shí)現(xiàn)繼承(Object Masquerading)
- 對(duì)象冒充實(shí)現(xiàn)單繼承
function ClassA(sColor){
this.name="Lily"
this.color=sColor;
this.sayColor=function () {
console.log(this.color)
}
}
function ClassB(sColor,sName) {
//newMethod()之前定義同名屬性和方法會(huì)被父類覆蓋
// this.name=sName;
// this.sayColor=function () {
// alert(sColor);
// }
this.newMethod=ClassA;
//調(diào)用方法后,相當(dāng)于給B類增加了sColor屬性和sayColor方法
this.newMethod(sColor);
//newMethod()之后同名方法會(huì)覆蓋父類
this.sayColor=function () {
alert(sColor);
}
// 從對(duì)象上刪除父類構(gòu)造函數(shù)
delete this.newMethod;
this.name=sName;
this.sayName=function () {
console.log(this.name);
}
}
var objA=new ClassA("blue");
var objB=new ClassB("red","John");
objA.sayColor(); // blue
objB.sayColor(); // red
objB.sayName(); // John
子類中定義的屬性和方法如果在調(diào)用this.newMethod()這行代碼之前,那么子類同名屬性和方法會(huì)被父類覆蓋,反之會(huì)覆蓋父類同名屬性和方法,理由很簡(jiǎn)單,原來(lái)的賦值被新值覆蓋
- 對(duì)象冒充實(shí)現(xiàn)多繼承
function ClassC(sColor,sName){
this.newMethod=ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.newMethod=ClassB;
this.newMethod(sColor,sName);
delete this.newMethod;
}
var obj=new ClassC("green","ClassC");
obj.sayName(); //ClassC
obj.sayColor(); // green
可見ClassC同時(shí)擁有ClassA和ClassB的特性
ClassA的同名屬性和方法會(huì)被ClassB覆蓋.同樣因?yàn)楹蠖x覆蓋了先定義
2. call()方法實(shí)現(xiàn)繼承
function sayColor(sPrefix,sSuffix){
console.log(sPrefix+this.color+sSuffix);
}
var obj=new Object();
obj.color="blue";
//會(huì)調(diào)用sayColor方法
sayColor.call(obj,"The color is "," a very nice color indeed.");
//下面與對(duì)象冒充一起使用
function ClassB(sColor,sName) {
// this.newMethod=ClassA;
// this.newMethod(sColor);
// delete this.newMethod;
//call就是方法調(diào)用沒啥特別地方,做了上面三條語(yǔ)句做的事
//調(diào)用構(gòu)造函數(shù)
ClassA.call(this,sColor);
this.name=sName;
this.sayName=function () {
console.log(this.name);
}
}
3. apply()方法實(shí)現(xiàn)繼承
function sayColor(sPrefix,sSuffix){
console.log(sPrefix+this.color+sSuffix);
}
var obj=new Object();
obj.color="blue";
// 普通的方法調(diào)用
sayColor.apply(obj,new Array("The color is ", " a very nice color indeed."));
function ClassB(sColor,sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
//調(diào)用構(gòu)造函數(shù)
// ClassA.apply(this,arguments)
ClassA.apply(this,new Array(sColor))
this.name=sName;
this.sayName=function () {
console.log(this.name);
}
}
var obj=new ClassB("red","Bill");
// 如果特意將ClassB的參數(shù)順序調(diào)整ClassA不同,這時(shí)就不能用arguments,該使用ClassA.apply(this,new Array(sColor)),感興趣自己試驗(yàn)一下
// ob.sayColor(); //Bill
obj.sayColor();
總結(jié):call()和apply()讓繼承變得更清爽,查看源碼你會(huì)發(fā)現(xiàn)是Function的原型方法。
4. 原型繼承
function object(o) {
function F() {}
F.prototype=o;
return new F();
}
var person = {
name:"EvanChen",
friends:["Shelby","Court","Van"]
};
var person1=object(person);
//先從person1對(duì)象查找name,沒找到會(huì)去原型對(duì)象上查找
console.log(person1.name);
es5以后,規(guī)范了這種繼承,創(chuàng)建對(duì)象使用Object.create()
//只傳一個(gè)參數(shù)時(shí)
var person1=Object.create(person);
console.log(person1.name);
//傳兩個(gè)參數(shù)時(shí)
var prop={son:{age:10}};
var person1=Object.create(person,prop);
總結(jié):Object.create傳入的第一個(gè)參數(shù)屬性會(huì)作為person1的原型屬性。第二個(gè)參數(shù)屬性會(huì)作為person1對(duì)象上的屬性
5. 原型鏈繼承
function ClassA() {}
ClassA.prototype.color="blue";
ClassA.prototype.sayColor=function () {
console.log(this.color);
}
function ClassB() {
}
ClassB.prototype=new ClassA();
var obj=new ClassB();
obj.sayColor(); //blue
console.log(obj.color); //blue
可見ClassB同時(shí)擁有了ClassA的屬性可方法
下面為ClassB添加更多原型方法
...
ClassB.prototype=new ClassA();
//下面的屬性和方法是在賦值ClassA為新原型之后添加的屬性和方法
ClassB.prototype.name="";
ClassB.prototype.sayName=function () {
console.log(this.name);
}
var classB=new ClassB();
classB.color="red";
classB.name="John";
classB.sayColor(); //red
classB.sayName(); // John
特別指出:
- ClassB原型對(duì)象上添加的新的屬性和方法,請(qǐng)務(wù)必添加在ClassB.prototype=new ClassA()之后。因?yàn)樵鸵呀?jīng)指向ClassA,舊原型對(duì)象被銷毀
- 通過修改類的原型對(duì)象方式?jīng)]辦法實(shí)現(xiàn)多繼承,因?yàn)閷?duì)象的原型對(duì)象僅有一個(gè)
- 對(duì)象和對(duì)象的原型上有同名屬性或方法,優(yōu)先會(huì)使用對(duì)象本身,如果對(duì)象上無(wú)此屬性,才會(huì)使用原型對(duì)象上同名屬性和方法
6. 混合構(gòu)造函數(shù)和原型鏈方式實(shí)現(xiàn)繼承
function ClassA(sColor) {
this.color=sColor;
}
ClassA.prototype.sayColor=function () {
console.log(this.color);
}
function ClassB(sColor,sName) {
ClassA.call(this,sColor);
this.name=sName;
}
ClassB.prototype=new ClassA();
//為ClassB添加新原型方法
ClassB.prototype.sayName=function () {
console.log(this.name);
}
var classA=new ClassA("purple");
var classB=new ClassB("red","John");
classA.sayColor(); // purple
classB.sayColor(); // red
classB.sayName(); // John
混合繼承結(jié)合了構(gòu)造函數(shù)創(chuàng)建各個(gè)對(duì)象擁有各自一份屬性和原型方法被所有對(duì)象共享的優(yōu)點(diǎn)
怎么樣簡(jiǎn)單吧,喜歡的話,幫忙點(diǎn)個(gè)贊O(∩_∩)O謝謝!