JavaScript ----------- 组合继承

继承

实现继承:继承实际的方法。ECMAScript 只支持实现继承,而且其实现基础主要是依靠原型链来实现的。

  基本思想是:利用原型来实现一个引用类型继承另外一个引用类型的属性和方法。

        原型 - 构造函数 - 实例 之间的关系

        构造函数(prototype) <-------> 原型(constructor) <------- 实例(_proto_)

实现原型链有一种基本模式,其代码大致如下

 1 function SuperType(){
 2 
 3 this.property = true;
 4 }
 5 
 6 SuperType.prototype.getSuperValue = function(){
 7     return this.prototype;
 8 }
 9 function SubType(){
10     this.subproperty = false;
11 }
12 
13 //继承了SuperType
14 
15 SubType.prototype = new SuperType();
16 
17 SubType.prototype.getSubValue = function(){
18     return this.subproperty;
19 } 
20 
21 var instance = new SubType();
22 alert(instance.getSuperValue());
23 
24 
25 function SuperType(){
26     this.property = true;
27 }
28 
29 SuperType.prototype.getSuperValue = function(){
30     return this.property;
31 }
32 
33 function SubType(){
34     this.subproperty = false;
35 }
36 SubType.prototype = new SuperType();
37 
38 SubType.property = {
39     getSubValue:function(){
40         return this.subproperty;
41     },
42     someOtherMethod:function(){
43         return false;
44     }
45 }
46 
47 var instance = new SubType();
48 alert(instance.getSuperValue());        

 


6.3.1 既在通过原型进行继承时,不能使用字面量的方法创建原型内容,因为这样会重写原型链

原型中存在的最大问题是:


  1 引用类型值得共用问题

  2 用原型实现的继承,由于属性共用,在创建子类型实例时,不能向超类型的构造函数中传递参数。

6.3.2 借用构造函数

  call() apply()


在解决原型中包含引用类型值所带来问题的过程中,可以使用一种叫借用构造函数的技术(有时候也叫做伪造对象或经典继承)。这种技术的基本思想相当简单,既在子类型构造函数的内部调用超类型构造函数。别忘了,函数
只不过是在特定环境中执行代码的对象,因此通过使用apply()和 call()方法也可以在新创建的对象上执行构造函数,

function SuperType(){
    this.colors = ["red","blue","green"];
}

function SubType(){
    SuperType.call(this);
}

var instance = new SubType();
instance.colors.push("black");

alert(instance.colors); //red blue green black

var instance1 = new SubType();


alert(instance1.colors); // red blue green

 

借用构造函数相比原型模式的优点:

· 传递参数

例如:

function SuperType(name){
    this.name = name;
}

function SubType(){
    SuperType.call(this,"Nicholas");
    this.age = 20;
}

var instance = new SubType();
alert(instance.name); // Nicholas
alert(instance.age); //20 

 



借用构造函数的问题
如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题------ 方法都在构造函数中定义,因此函数复用就无从谈起了。

 

6.3.3  

组合继承(combination inheritance) 原型与借用构造函数两种方法取其长的一种组合方式

主要思想:
  利用原型对属性和方法的继承 而通过借用构造函数来实现对实例属性的继承。

这样既然继承原型中属性,又能保证实例拥有自己的属性。

    
       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.constructor = SubType;
        SubType.prototype.sayAge = function(){
            alert(this.age);
        }
        
        var instance1 = new SubType("Nicholas",20);
        instance1.colors.push("black");
        alert(instance1.colors);
        instance1.sayName();
        instance1.sayAge();
        
        var instance2 = new SubType("Greg",27);
        alert(instance2.colors);
        instance2.sayName();
        instance2.sayAge
        
  

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  在这个例子中,SuperType 构造函数定义了两个属性: name 和 colors. SuperType的原型定义了一个方法sayName(). SubType()构造函数在调用 SuperType 构造函数时传入了name参数,紧接着又定义了它自己的属性age。

然后,将SuperType的实例赋值给SubType的原型,然后又在新原型上定义了方法sayAge(). 这样一来,就可以让两个不同的SubType实例既分别拥有自己的属性----包括colors 属性,又可以使用相同的方法了。

  组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点。 而且 instanceof 和 isPrototypeOf 也能够用于识别基于组合继承创建的对象。

 

posted @ 2016-06-25 13:33  czhyuwj  阅读(205)  评论(0编辑  收藏  举报