带你看懂JavaScript的继承(五) 组合继承

楼主最近项目紧张,所以更新比较慢哈,但楼主本着质量第一,速度第二的理念,宁缺毋滥。好了,我们继续。上一期我们留了一个思考题,当我们采用经典继承的方法,解决了原型链的原罪问题,可是我们又创造了新的问题:函数的复用和原型中方法对后代的不可见性。

现在我们来解决这个问题,标题剧透啦,就是用组合继承的方法。组合继承,又叫伪经典继承。顾名思义,指的是将原型链和经典继承的技术组合到一块的技术。记下来这句话慢慢体会:

使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function SuperType(name){
this.name = name;
this.colors = ["red","blue"];
}

SuperType.prototype.sayName = function(){
console.log(this.name)
}

function SubType(name, age){
//继承属性
SuperType.call(this.name);
this.age = age;
}

//继承方法
SubType.prototype = new SuperType();
//!!!!!!!!!构造函数指回自己,精髓就在这里
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge(){
console.log(this.age);
}
var instance1 = new SubType("SHUAI",18);
instance1.colors.push("black");
console.log(instance1.colors); //["red","blue","black"]
instance1.sayName(); //"SHUAI"
instance2.sayAge(); //18

var instance2 = new SubType("XUE",11);
instance2.colors.push("blue"); //["red","blue","blue"]
instance2.sayName(); //"XUE"
instance2.sayAge(); //11

这段代码重点在感叹号那里,组合是继承就是在把子类型的prototype指向超类型实例后,又将其构造函数constructor指回子类型。这样在实例化时,构造函数使用的子类型的构造函数,而prototype中的其他属性和方法都能继承自超类型。这样就避免了原型链和经典继承的缺点,融合了他们的优点。也是众多JSCoders最常用的继承方式。

再拓展一点好处就是,除了上面的优点外,在你使用instanceof和isPrototypeOf()时,既享受了福利,也能让你清楚地识别基于组合继承创建的对象。

这一期就先介绍到这里了,这一系列到了一半了,请大家从头总结一下我们这半个系列所讨论到的知识点。因为我们接下来的继承技术在风格上会和现在有一些不同。建议手动用代码实现一下,毕竟,好记性不如烂笔头,对吧。下期见。