1. 組合繼承:又叫偽經典繼承,是指將原型鏈和借用構造函數(shù)技術組合在一塊的一種繼承方式。
下面來看一個例子:
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);
? }
? var instance1 = new SubType("Nicholas", 29);
? instance1.colors.push("black");
? alert(instance1.colors); //red,blue,green,black
? instance1.sayName(); //Nicholas
? instance1.sayAge(); //29
? var instance2 = new SubType("Greg", 27);
? alert(instance2.colors); //red,blue,green
? instance2.sayName(); //Greg
? instance2.sayAge(); //27
組合繼承避免了原型鏈和借用構造函數(shù)的缺陷,融合它們的優(yōu)點。
2. 原型式繼承
可以在不必預先定義構造函數(shù)的情況下實現(xiàn)繼承,其本質是執(zhí)行對給定對象的淺復制。而復制得到的副本還可以得到進一步的改造。
function object(o) {
? ? function F(){};
? ? F.prototype = o;
? ? return new F;
? }
? var person = {
? name: "Nicholas",
? friends: ["Shelby", "Court", "Van"]
? };
? var antherPerson = object(person);
? antherPerson.name = "Greg";
? antherPerson.friends.push("Rob");
? var antherPerson = object(person);
? antherPerson.name = "Linda";
? antherPerson.friends.push("Barbie");
? alert(person.friends); //Shelby,Court,Van,Rob,Barbie
3. 寄生式繼承
與原型式繼承非常相似,也是基于某個對象或某些信息創(chuàng)建一個對象,然后增強對象,最后返回對象。為了解決組合繼承模式由于多次調用超類型構造函數(shù)而導致的低效率問題,可以將這個模式與組合繼承一起使用。
function object(o) {
? ? function F(){};
? ? F.prototype = o;
? ? return new F;
? }
? function createAnother(original) {
? ? var clone = object(original);
? ? clone.sayHi = function() {
? ? ? alert("Hi");
? ? };
? ? return clone;
? }
? var person = {
? ? name: "Nicholas",
? ? friends: ["Shelby", "Court", "Van"]
? };
? var anotherPerson = createAnother(person);
? anotherPerson.sayHi();
4. 寄生組合式繼承
集寄生式繼承和組合繼承的優(yōu)點與一身,是實現(xiàn)基本類型繼承的最有效方式。
//繼承原型
? function extend(subType, superType) {
? ? function F(){};
? ? F.prototype = superType.prototype;
? ? var clone = new F;
? ? clone.constructor = subType;
? ? subType.prototype = clone;
? }
? //超類方法
? function SuperType(name) {
? ? this.name = name;
? ? this.colors = ["red", "blue", "green"];
? }
? SuperType.prototype.sayName = function() {
? ? return this.name;
? }
? //子類方法
? function SubType(name, age) {
? ? SuperType.call(this, name);
? ? this.age = age;
? }
? //繼承超類的原型
? extend(SubType, SuperType);
? //子類方法
? SubType.prototype.sayAge = function() {
? ? return this.age;
? }
? var instance1 = new SubType("Shelby");
? var instance2 = new SubType("Court", 28);
? instance1.colors.push('black');
? alert(instance1.colors); //red,blue,green,black
? alert(instance2.colors); //red,blue,green
? alert(instance1 instanceof SubType); //true
? alert(instance1 instanceof SuperType); //true
這段例子的高效率體現(xiàn)在它只調用了一次SuperType構造函數(shù),并且因此避免了在SubType.prototype上面創(chuàng)建不必要的多余的屬性。與此同時,原型鏈還能保持不變。因此,還能正常使用instanceof 和 isPrototypeOf()。開發(fā)人員普遍認為寄生組合式繼承是引用類型最理想的繼承范式。
5.多重繼承
繼承一般包括單向繼承和多向繼承,單向繼承模式較為簡單,每個子類有且僅有一個超類,多重繼承是一個比較復雜的繼承模式。一個子類可擁有多個超類。JavaScript原型繼承不支持多重繼承,但可通過混合模式來實現(xiàn)多重繼承。下面讓類C來繼承類A和類B:
function A(x){
? ? this.x = x;?
}?
A.prototype.hi = function(){?
? ? console.log('hi');?
}?
function B(y){?
? ? this.y = y;?
}?
B.prototype.hello = function(){?
? ? console.log('hello');?
}?
// 給Function增加extend方法?
Function.prototype.extend = function(obj) {?
? ? for(var item in obj) {?
? ? ? ? this.constructor.prototype[item] = obj[item];?
? ? }?
}?
// 在類C內部實現(xiàn)繼承?
function C(x,y){?
? ? A.call(this,x);?
? ? B.call(this,y);?
};?
C.extend(new A(1));?
C.extend(new B(2));?
// 通過復制繼承后,C變成了一個對象,不再是構造函數(shù)了,可以直接調用?
C.hi(); // hi?
C.hello(); // hello?
console.log(C.x); // 1?
console.log(C.y); // 2