這一次要講 組合、原型式、寄生式、寄生組合式繼承方式。
1. 組合繼承:又叫偽經典繼承,是指將原型鏈和借用構造函數技術組合在一塊的一種繼承方式。
下面來看一個例子:

1 function SuperType(name) { 2 this.name = name; 3 this.colors = ["red", "blue", "green"]; 4 } 5 SuperType.prototype.sayName = function() { 6 alert(this.name); 7 } 8 function SubType(name, age) { 9 SuperType.call(this, name); 10 this.age = age; 11 } 12 13 //繼承方法 14 SubType.prototype = new SuperType(); 15 SubType.prototype.sayAge = function() { 16 alert(this.age); 17 } 18 19 var instance1 = new SubType("Nicholas", 29); 20 instance1.colors.push("black"); 21 alert(instance1.colors); //red,blue,green,black 22 instance1.sayName(); //Nicholas 23 instance1.sayAge(); //29 24 25 var instance2 = new SubType("Greg", 27); 26 alert(instance2.colors); //red,blue,green 27 instance2.sayName(); //Greg 28 instance2.sayAge(); //27
組合繼承避免了原型鏈和借用構造函數的缺陷,融合它們的優點。
2. 原型式繼承
可以在不必預先定義構造函數的情況下實現繼承,其本質是執行對給定對象的淺復制。而復制得到的副本還可以得到進一步的改造。

1 function object(o) { 2 function F(){}; 3 F.prototype = o; 4 return new F; 5 } 6 7 var person = { 8 name: "Nicholas", 9 friends: ["Shelby", "Court", "Van"] 10 }; 11 12 var antherPerson = object(person); 13 antherPerson.name = "Greg"; 14 antherPerson.friends.push("Rob"); 15 16 var antherPerson = object(person); 17 antherPerson.name = "Linda"; 18 antherPerson.friends.push("Barbie"); 19 20 alert(person.friends); //Shelby,Court,Van,Rob,Barbie
3. 寄生式繼承
與原型式繼承非常相似,也是基於某個對象或某些信息創建一個對象,然后增強對象,最后返回對象。為了解決組合繼承模式由於多次調用超類型構造函數而導致的低效率問題,可以將這個模式與組合繼承一起使用。

1 function object(o) { 2 function F(){}; 3 F.prototype = o; 4 return new F; 5 } 6 function createAnother(original) { 7 var clone = object(original); 8 clone.sayHi = function() { 9 alert("Hi"); 10 }; 11 return clone; 12 } 13 14 var person = { 15 name: "Nicholas", 16 friends: ["Shelby", "Court", "Van"] 17 }; 18 19 var anotherPerson = createAnother(person); 20 anotherPerson.sayHi();
4. 寄生組合式繼承
集寄生式繼承和組合繼承的優點與一身,是實現基本類型繼承的最有效方式。

1 //繼承原型 2 function extend(subType, superType) { 3 function F(){}; 4 F.prototype = superType.prototype; 5 6 var prototype = new F; 7 prototype.constructor = subType; 8 subType.prototype = prototype; 9 } 10 11 //超類方法 12 function SuperType(name) { 13 this.name = name; 14 this.colors = ["red", "blue", "green"]; 15 } 16 SuperType.prototype.sayName = function() { 17 return this.name; 18 } 19 20 //子類方法 21 function SubType(name, age) { 22 SuperType.call(this, name); 23 this.age = age; 24 } 25 26 //繼承超類的原型 27 extend(SubType, SuperType); 28 29 //子類方法 30 SubType.prototype.sayAge = function() { 31 return this.age; 32 } 33 34 var instance1 = new SubType("Shelby"); 35 var instance2 = new SubType("Court", 28); 36 37 instance1.colors.push('black'); 38 39 alert(instance1.colors); //red,blue,green,black 40 alert(instance2.colors); //red,blue,green 41 42 alert(instance1 instanceof SubType); //true 43 alert(instance1 instanceof SuperType); //true
這段例子的高效率體現在它只調用了一次SuperType構造函數,並且因此避免了在SubType.prototype上面創建不必要的多余的屬性。與此同時,原型鏈還能保持不變。因此,還能正常使用instanceof 和 isPrototypeOf()。開發人員普遍認為寄生組合式繼承是引用類型最理想的繼承范式。