zoukankan      html  css  js  c++  java
  • Javascript之继承(其他方式)

    1.借用构造函数
    在解决原型中包含引用类型值所带来的问题的过程中,我们可以使用一种叫借用构造函数的技术(又称伪造对象或经典继承)。就是在子类型构造函数的内部调用父类型构造函数,记住,函数只不过是在特定环境中执行代码的对象,可以通过使用apply()和call()方法也可以在(将来)新创建的对象上执行构造函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function SuperType(){
        this.colors=["red","blue","green"];
        }
          
    function SubType(){
        //继承了SuperType
        SuperType.call(this);
    }
      
    var instance=new SubType();
    instance.colors.push("black");   //"red","blue","green","black"
    alert(instance.colors);
      
    var instance2=new SubType();
    alert(instance2.colors);          //"red","blue","green"

    将SuperType构造函数放到SubType的执行环境中,这样一来,就会在新SubType对象上执行SuperType()函数中定义的所有对象初始化代码,结果,SubType的每一个实例都有一份具有自己colors属性的副本。

    (1)传递参数

    借用构造函数可以在子类型构造函数中向父类型构造函数传递参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function SuperType(name){
        this.name=name;
        }
          
    function SubType(){
        //继承了SuperType,同时传递参数
        SuperType.call(this,"zxj");
          
        //实例属性
        this.age=29;
        }
      
    var instance=new SubType();
    alert(instance.name);         //zxj
    alert(instance.age);          //29

    (2)借用构造函数的问题

    如果仅仅使用借用构造函数,那么将无法避免构造函数模式存在的问题——方法都在构造函数中定义,函数的复用也无从谈起。所以借用构造函数也很少单独使用。

    2.组合继承

    组合继承(伪经典继承),指的是将原型链和借用构造函数的技术组合在一块。其思路是使用原型链对原型属性和方法的继承,而通过借用构造函数来实现对实例对象的继承

    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","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 instance=new SubType("zxj",29);
    instance.colors.push("black");   
    alert(instance.colors);              //"red","blue","green","black"
    instance.sayName();                  //zxj
    instance.sayAge();                   //29     
      
    var instance2=new SubType("Greg",28);
    alert(instance.colors);              //"red","blue","green","black"
    instance2.sayName();                 //Greg    
    instance2.sayAge();                  //28

    组合继承避免了原型链和借用构造函数的缺陷,融合了他们的有点,成为JavaScript中追尾常用的继承模式。而且,instanceof和isPrototypeof()也能够用于识别组合继承创建的对象。

    3.原型式继承

    ​借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

    1
    2
    3
    4
    5
    function object(o){
        function F(){};
        F.prototype=o;
        return new F();
    }

    在object()函数内部,先创建一个临时性的构造函数,然后将传入的对象作为该构造函数的原型,最后返回这个临时类型的一个新实例。本质上讲,object()对传入其中的对象进行了一次浅复制。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function object(o){ 
        function F(){}; 
        F.prototype=o; 
        return new F(); 
    }
    var person={
        name:"zxj",
        friends:["Shelby","Court","Van"]
    };
      
    var anotherPerson=object(person);
    antherPerson.name="Greg";
    anotherPerson.friends.push("Rob");
      
    var yetAnotherPerson=object(person);
    yetAnotherPerson.name="Linda";
    yetAnotherPerson.friends.push("Brabie");
      
    alert(person.friends); //"Shelby,Court,Van,Rob,Brabie"

    但包含引用类型值的属性始终后悔共享相应的值,这和原型模式一样的。

    4.寄生式继承

    寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式类增强对象,最后再像真的是它做了所有工作一眼放回对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function creteAnother(original){
        var clone=object(original);   //通过调用函数创建一个新对象
        clone.sayHi=function(){       //以某个方式来增强这个对象
            alert("hi");
        }
        return clone;                 //返回这个对象          
    }
      
    var person={
        name:"zxj",
        friends:["Shelby","Court","Van"]
    };
      
    var anotherPerson=createAnother(person);
    anotherPerson.sayHi();  //"hi"

    使用寄生式来为对象添加函数,会由于不能做到函数服用而降低效率。

    5.寄生组合式继承

     组合继承是JavaScript中最常用的继承模式,但它无论在什么情况下,都会调用两次父类型构造函数:一次在创建子类型原型时,一种在子类型构造函数内部。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function SuperType(name){
        this.name=name;
        this.colors=["red","blue","green"];
        }
    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);
        }

    第一次调用父类型时,SubType.prototype会得到两个属性:name和colors;他们都是SuperType的实例属性,只不过位于SubType的原型中。带调用SubType构造函数时,有一次调用了SuperType构造函数,这一次是在新对象上创建实例属性name和colors,于是这两个属性就屏蔽掉了原型中的两个同名属性,调用过程如图所示。

     

    这样就有两组name和colors属性:一组在实例上,一组在SubType的原型中,这就是调用两次SuperType构造函数的结果。

    当然,我们可以通过寄生组合是继承来解决这问题,所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链来继承方法。思路:不必为了指定子类型的原型而调用父类型的构造函数,我们只需父类型原型的一个副本。本质上,就是使用寄生式继承来继承父类型的原型,然后将结果指定给子类型的原型,寄生组合式继承的基本模式如下: 

    1
    2
    3
    4
    5
    function inheritPrototype(subType,superType){
       var prototype=object(superType.prototype);   //创建对象
        prototype.constructor=subTyoe;              //增强对象
        subType.prototype=prototype;                //指定对象
    }

     示例中inheritPrototype()函数实现了寄生组合式继承的最简单形式。这个函数接收两个参数:子类型构造函数和父类型构造函数。在函数内部:第一步是创建父类型原型的一个副本。第二步是为创建的副本调价constructor属性,从而弥补因重写原型而失去默认的constrcutor属性。最后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我就可以调用inheritPrototype()函数的语句,去替换前面例子中为子类型原型赋值的语句。

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    function object(o){
              function F(){}
              F.prototype = o;
              return new F();
          }
        
          function inheritPrototype(subType, superType){
              var prototype = object(superType.prototype);   //create object
              prototype.constructor = subType;               //augment object
              subType.prototype = prototype;                 //assign object
          }
                                    
          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;
          }
     
          inheritPrototype(SubType, SuperType);
            
          SubType.prototype.sayAge = function(){
              alert(this.age);
          };
            
          var instance1 = new SubType("Nicholas", 29);
          instance1.colors.push("black");
          alert(instance1.colors);  //"red,blue,green,black"
          instance1.sayName();      //"Nicholas";
          instance1.sayAge();       //29
            
           
          var instance2 = new SubType("Greg", 27);
          alert(instance2.colors);  //"red,blue,green"
          instance2.sayName();      //"Greg";
          instance2.sayAge();       //27




  • 相关阅读:
    [Unity热更新]04.卸载方式
    [Unity热更新]03.加载方式
    [Unity热更新]02.依赖关系
    [Unity热更新]01.打包与加载基础
    [Unity优化]批处理05:UGUI
    [Unity优化]gc02:StringBuilder
    [Unity优化]gc01:字符串常量池
    虚拟机中安装centos系统的详细过程
    零基础学习java------40---------Maven(maven的概念,安装,maven在eclipse中使用),springboot(spring整合springmvc(注解),spring整合mybatis(常见的配置文件)),前端页面(bootstrap软件)
    零基础学习java------39---------json格式交互,Restful(不懂),静态资源映射,SSM整合(ssm整合思想,application.xml文件详解(声明式事务管理),)
  • 原文地址:https://www.cnblogs.com/zxj159/p/3093524.html
Copyright © 2011-2022 走看看