mackxu
子曰:学而时习之,不亦说乎?
  1. 原型链(父类的实例)
  2. 借用构造函数(调用超类构造函数)
  3. 组合继承(原型链和借用构造函数)
  4. 原型式继承(借助原型基于已有的对象上创建新对象)
  5. 寄生式继承(创建一个仅用于封装继承过程的函数)
  6. 寄生组合式继承(解决父类属性重写)

ECMAScript无法实现接口继承,只支持实现继承,而且其实现继承主要依靠原型链来实现的

原型链

思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。

 1 function A() {
 2     this.name = 'A';
 3 }
 4 A.prototype = {
 5     sayName: function() {
 6         return this.name;
 7     }
 8 };
 9 function B() {
10     this.name = 'B';
11 }
12 //通过原型链继承对象A
13 B.prototype = new A();
14 var b = new B();
15 debug(b.sayName());        //'B'

 

1、 别忘记默认的原型(所有引用类型默认都继承Object,且通过原型链继承)

2、 确定原型和实例的关系

instanceof操作符和isPrototype()方法。

3、 谨慎地定义方法

给子类添加原型的方法的代码一定要放在替换原型的语句之后。

通过原型链实现的继承时,不能使用对象字面量创建原型方法。这样会重写原型方法。

4、 原型链问题

1、 创建子类时不能向超类的构造函数传递参数

2、 超类包含引用类型的属性,通过原型来实现继承时,实际上会变成另一个类型的实例,于是乎超类的实例的所有属性变成了子类的原型属性了。因而引发了共享属性问题(特别是引用类型属性)

借用构造函数(经典继承)

思想:在子类型构造函数的内部调用超类型构造函数。

 1 function A() {
 2     this.colors = ['red', 'blue', 'green'];
 3 }
 4 //借用构造函数实现继承
 5 function B() {
 6     A.call(this);        //把A在B的环境中执行,A与B中的this对象指向B的实例
 7 }
 8 var b = new B();
 9 b.colors.push('black');
10 debug(b.colors);        //['red', 'blue', 'green', 'black']
11 var b2 = new B();
12 debug(b2.colors);    //['red', 'blue', 'green']
13 1、    向超类中传递参数
14 function A(name) {
15     this.name = name;
16 }
17 //借用构造函数实现继承
18 function B(name, age) {
19     //把A在B的环境中执行,A与B中的this对象指向B的实例
20     A.call(this, name);
21     this.age = age;        
22 }
23 var b = new B('mackxu', 22);
24 debug('我的名字是:'+b.name+" 我的年龄:"+b.age);

2、 借用构造函数的问题

1)  与构造函数模式一样的问题:在构造函数中定义的方法,无法共享。

2)  更苦逼的事:在超类的原型中定义的方法,对子类不可见

组合继承:(伪经典继承)

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

结果:既通过在原型上定义方法实现了函数的复用,又能够保证每个实例都有它自己的属性。

问题:无论什么情况下,都会调用两次超类型构造函数。一次在创建子类型原型时候、另一次在子类型构造函数内部。造成不得不在子类型构造函数中重写父类的属性。

解决办法:寄生组合式继承[改写了原型链继承]

 1 function A(name) {
 2     this.name = name;
 3     this.colors = ['red', 'blue', 'green'];
 4 }
 5 A.prototype = {
 6     sayName: function() {
 7         return this.name;
 8     }
 9 }
10 //借用构造函数实现继承超类属性
11 function B(name, age) {
12     //把A在B的环境中执行,A与B中的this对象指向B的实例
13     A.call(this, name);
14     this.age = age;        
15 }
16 //原型链继承超类的属性(方法和属性)
17 B.prototype = new A();
18 //此处不能用对象字面量赋值(原因前面已经给出)
19 B.prototype.sayAge = function() {
20     return this.age;
21 }
22 var b = new B('mackxu', 22);
23 debug('我的名字是:'+b.sayName()+" 我的年龄:"+b.sayAge()+" 我喜欢的颜色:"+b.colors);

原型式继承

借助原型可以基于已有对象创建新对象

1 function object(obj) {
2     function F(){}
3     F.prototype = obj;        //对其进行一次浅复制
4     return new F();
5 }

寄生式继承(类寄生构造函数模式、工厂模式)

思路:创建一个仅用于封装继承过程的函数

function createAnother(A) {
    var clone = object(A);
    //以某种方式来增强这个对象
  clone.sayHi = function() {
    debug(‘Hi’);
};
  return clone;
}

寄生组合式继承

 1 //改写原型链继承:
 2 function inheritPrototype(subType, superType) {
 3     var prototype = object(superType.prototype);    //创建对象[超类原型副本]
 4     prototype.constructor = subType;                    //增强对象
 5     subType.prototype = prototype;                    //指定对象
 6 }
 7 代码:
 8 //创建对象的一般步骤[原型式继承]
 9 function object(obj) {
10     function F() {}
11     F.prototype = obj;
12     return new F();
13 }
14 /**
15  * 改写原型链继承
16  * @param {object} subType 子类构造函数
17  * @param {object} superType  超类构造函数
18  */
19 function inheritPrototype(subType, superType) {
20     var prototype = object(superType.prototype);    //创建对象[超类原型副本]
21     prototype.constructor = subType;                //增强对象
22     subType.prototype = prototype;                    //指定对象
23 }
24 function A(name) {
25     this.name = name;
26     this.colors = ['red', 'blue', 'green'];
27 }
28 A.prototype = {
29     sayName: function() {
30         return this.name;
31     }
32 }
33 //借用构造函数实现继承超类属性
34 function B(name, age) {
35     //把A在B的环境中执行,A与B中的this对象指向B的实例
36     A.call(this, name);
37     this.age = age;        
38 }
39 //B.prototype = new A(); //原型链继承超类的属性(方法和属性)
40 //寄生组合式继承
41 inheritPrototype(B, A);
42 //此处不能用对象字面量赋值(原因前面已经给出)
43 B.prototype.sayAge = function() {
44     return this.age;
45 }
46 var b = new B('mackxu', 22);
47 debug('我的名字是:'+b.sayName()+" 我的年龄:"+b.sayAge()+" 我喜欢的颜色:"+b.colors);

整理自JavaScript高级程序设计

posted on 2012-11-18 14:16  mackxu  阅读(523)  评论(0编辑  收藏  举报