zoukankan      html  css  js  c++  java
  • javascript中的继承-寄生组合式继承

      前文说过,组合继承是javascript最常用的继承模式,不过,它也有自己的不足:组合继承无论在什么情况下,都会调用两次父类构造函数,一次是在创建子类原型的时候,另一次是在子类构造函数内部.子类最终会包含父类对象的全部实例属性,但我们不得不在调用子类构造函数时重写这些属性.请再看一次组合继承的例子:

    function SuperType(name){
           this.name=name;
           this.friends=["gay1","gay2"];  
    }
    SuperType.prototype.sayName=function(){
           alert(this.name);
    };
    funciton SubType(name,age){
          SuperType.call(this,name); //第二次调用SuperType();
          this.age=age;  
    }
    SubType.prototype=new SuperType();  //第一次调用SuperType()
    SubType.prototype.sayAge=function(){
          alert(this.age);
    };

      在第一次调用SuperType构造函数时,SubType.prototype会得到两个属性:name和friends,他们都是SuperType的实例属性.只不过现在位于SubType的原型中.当调用SubType构造函数时,又会调用一次SuperType构造函数,这一次又在新对象上创建了实例属性name和friends.于是,这两个属性就屏蔽了原型中的两个同名属性.

      结果是,有两组name和friends属性,一组在SubType的实例上,一组在SubType的原型上.这就是调用两次SuperType构造函数的结果.而现在,找到了解决这个问题的方法:寄生组合式继承.

      寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法.思路:不必为了指定子类的原型而调用父类的构造函数,我们所需要的无非就是父类原型的一个副本而已.本质上,就是使用寄生式继承来继承父类的原型,然后在将结果指定给子类的原型:

    function inheritPrototype(subType,superType){
          var prototype=object(superType.prototype); //创建父类原型的一个副本 等同于使用Object.create(superType.prototype)
          prototype.constructor=subType;   //为副本添加constructor属性,弥补重写原型而失去的constructor属性
          subType.prototype=prototype; //将创建的对象(副本)赋值给子类的原型
    }

      这样,我们就可以通过调用inheritPrototype()函数,替换前面例子中为子类原型的赋值语句了:

    function inheritPrototype(subType,superType){
          var prototype=Object.create(superType.prototype); //创建父类原型的一个副本 等同于使用Object.create(superType.prototype)
          prototype.constructor=subType;   //为副本添加constructor属性,弥补重写原型而失去的constructor属性
          subType.prototype=prototype; //将创建的对象(副本)赋值给子类的原型
    }
    function SuperType(name){
          this.name=name;
          this.friends=["gay1","gay2"];
    }
    SuperType.prototype.sayName=function(){
          alert(this.name);
    };
    function SubType(name,age){
          SuperType.call(this,name);  //继承SuperType
          this.age=age;       //扩展出age属性
    }
    inheritPrototype(SubType,SuperType);
    SubType.prototype.sayAge=function(){
           alert(this.age);
    };//扩展出sayAge方法
    
    var person1=new SubType("nUll",25);
    var person2=new SubType("mywei",25);
    person1.friends.push("gay3");
    person1.sayName();
    person1.sayAge();
    alert(person1.friends);    //gay1,gay2,gay3
    alert(person2.friends); //gay1,gay2
    alert(person1 instanceof SubType);   //true
    alert(person1 instanceof SuperType);  //true
    alert(SubType.prototype.isPrototypeOf(person1));  //true
    alert(SuperType.prototype.isPrototypeOf(person1)); //true

      这个例子的高效率体现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上创建不必要的 多余的属性.与此同时,原型链还能保持不变.因此,还能够正常使用instanceof 和isPrototypeOf确定继承关系.

         YUI的YAHOO.lang.extend()方法采用了寄生组合式继承。

       

  • 相关阅读:
    Wwise音频解决方案概述
    图形学中的几何光学理论与视觉现象
    Visual Studio 2015 Tools for Unity使用基础
    C++编译器优化技术:RVO、NRVO和复制省略
    【ElasticSearch】 ElasticSearch基本概念和RESTful API(四)
    【ElasticStack】入门介绍(三)
    【Java】开发一个Java-SDK
    【Java】Maven 打包可运行jar包
    【SpringBoot】Spring Boot Admin 微服务应用监控
    【Java面试题】方法的参数传递机制
  • 原文地址:https://www.cnblogs.com/nullcnb/p/3671971.html
Copyright © 2011-2022 走看看