JavaScript中的继承
浅述JS继承
JS作为一门不是很严谨的OO语言,由于其函数没有签名,因此不能实现签名继承的接口形式,却可实现属性与方法的完全继承。
JS的继承方式有六种:原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承及寄生组合继承。
原型链继承
在JS对象一章讲到了构造函数的原型对象,如果一个构造函数的原型对象是另一个构造函数的实例,那么通过该构造函数创建的实例就继承了原型对象对应构造函数的全部属性与方法。
1 | function SuperType(name){ |
不足:1. 对于父类的引用类型,在子类中是共享的,因为子类原型对象指向同一父类实例,无法实现与子类的单独绑定。 2. 没有办法在不影响子类的情况下为父类构造函数赋予初始值。
构造函数继承
在子类构造函数中,调用父类构造函数方法,可以实现父类属性(尤其是引用类型)与子类的单独绑定。
1 | function SuperType(name){ |
不足:无法复用父类原型对象中公共的属性与方法。
组合继承
组合继承就是综合原型链与构造函数的继承方式,结合二者各自的优点,可以继承父类构造函数与原型对象中的属性与方法,且可以实现父类引用类型数据与子类的单独绑定。
1 | function SuperType(name){ |
不足: 重复调用了两次的父类的构造函数,导致子类原型对象中存储了重复的无用的数据。
原型式继承
如果只想使得某些类表现得像某个类,可以采用原型式继承。即使这些类的原型对象指向同一个对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23var Person = {
name: "syz",
friends: ["mzp", "wjh"]
}
// 原型继承函数
function object(o){
function F(){}
F.prototype = o;
return new F;
}
var person1 = object(Person);
person1.name = "John";
person1.friend.push("lili");
var person2 = object(Person);
person1.name = "gad";
person1.friend.push("uzi");
console.log(person1.name); // John
console.log(person2.name); // gad
console.log(person1.friends); // [ 'mzp', 'wjh', 'lili', 'uzi' ]
console.log(person2.friends); // [ 'mzp', 'wjh', 'lili', 'uzi' ]
ECMAScript5规范了原型式继承的方式,即采用Object.create()方法,参数数即要继承的包含共用的属性与方法的对象,第二个参数为可选参数Object.defineProperties()方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。
Object.create()作用与object()方法相同。
1 | var Person = { |
寄生继承
寄生继承组合了原型式继承与工厂方法,或者是装饰器模式,可以对原型示例添加装饰方法。
1 | var Person = { |
寄生组合继承
是JS继承的最优解,通过寄生继承减少了组合继承中多余的父类构造函数调用产生的子类原型对象属性重复的问题。
对于子类的原型对象,采用寄生继承方式继承自父类的原型对象。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
26function SuperType(name){
this.name= name;
this.color = ["red", "green", "blue"];
}
SuperType.prototype.sayHello = function(){
console.log("Hello " + this.name);
}
function inheritPrototype(subType, superType){
subType.prototype = Object.create(superType.prototype);
subType.prototype.constructor = subType;
}
function SubType(name,age){
SuperType.call(this,name);
this.age=age;
}
inheritPrototype(SubType,SubType);
var sub = new SubType("syz", 12);
console.log(sub.name); // syz
console.log(sub.age); // 12
console.log(sub.color); // [ 'red', 'green', 'blue' ]
sub.sayHello(); // Hello syz
完美!