• JavaScript学习笔记(三)—— 继承的实现


    一、JavaScript实现继承的三层含义:
     
        ① 子类的实例可以共享父类的方法;
        ② 子类可以覆盖父类的方法或者扩展新的方法;
        ③ 子类和父类都是子类的实例。
     

    二、实现继承的几种方法:
     
    1、原型链继承
    例:function Box( ){           //被继承的函数叫超(父)类型;
         this.name = “Andy”;
         }
           function Desk( ){           //继承的函数叫子类型
         this.age = 25; 
         }
    Desk.prototype = new Box( );   //将Box构造里的信息和原型信息都给Desk
    var desk = new Desk( );
    alert(desk.name);    //返回 Andy;
     
    Desk.prototype.name = "Jack”; //重写父类型中的属性
    var desk2 = new Desk();          
    alert(desk2.name);   //返回 Jack;
     
    ps:  ① 如上例,若子类型要重写父类型中某个方法或属性,给原型添加的代码一定要放在替换原型的语句之后。
           ② 在通过原型链继承时,不能使用字面量创建原型对象,这样会重写原型链
         

    2、对象冒充法(即 借用构造函数)
         解决引用共享和超类型无法传参的问题,采用“对象冒充”技术继承。
    例:function Box (name,age){
           this.name  = “Andy”;
           this.age = 25;
           this.family = [“姐姐”,“哥哥”,“妹妹”];
           }
     
          function Desk(name,age){
            Box.call(this,name,age)        //Desk 冒充 Box  
          }
       
          var desk = new Desk( );
          alert(desk.name);    //返回 Andy
          alert(desk.family);   //返回 姐姐,哥哥,妹妹
     
    PS
           ① call和apply方法都可以实现继承,两者的第二个参数不同,call是一个个的参数列表 
           apply的第二个参数是数组。
           例:Box.call(this,name,age);
                 Box.apply(this,[name,age]);
     
           ② 对象冒充只能继承构造里的信息
           例:接上例添加:
                Box.prototype.family = “家庭”;
                alert(desk.family);    //继承不了,仍然返回 姐姐、哥哥、妹妹
           

    3、组合继承法(对象冒充+原型链继承方式)
    使用原型链实现对原型属性和方法的继承,使用对象冒充来实现对实例属性的继承
    例:function Box(name,age){
            this.name = name;
            this.age = age;  
    }  
    Box.prototype.work = function(){
           return  this.name+this.age+”运行中”;
       }
          function Desk(name,age){
           Box.call(this,name,age)             //对象冒充,构造里继承
         }
    Desk.prototype = new Box( );        //原型链继承
    var desk = new Desk(“Andy”,25);
    alert(desk.work( ) );   //返回 Andy 25 运行中
     

    小 结   
    原型链继承中,包含引用类型值的原型的原型属性会被所有实例共享,并且创建子类型的实例时,不能向超类型的构造函数中传递参数,因此实践中很少会单独使用原型链。
     
    对象冒充(借用构造函数法)中,可以通过call()或者apply()方法在新创建的对象上实行构造函数,解决了原型链继承法中共享和无法传参的问题。但对象冒充只能继承构造里的信息,会导致函数无法复用
     
    组合继承中,使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承,既能实现函数复用,又能保证每个实例都有自己的属性,因此,成为JavaScript常用的继承模式(唯一问题:超类型会被调用两次

    4、原型式继承(与原型链继承类似)
    例://临时中转函数
            function obj(o){      //o表示将要传递进入的一个对象
            function  F( ){ }           // 临时新建的对象,用来储存传递过来的对象
            F.prototype = o;        //将o对象实例赋值给F构造的原型对象
            return new F( );
           }
         var box = {                     //相当于 var box = new Box();
               name:”Andy”,
               age:28,
               family:[“哥哥”,“姐姐”]
               }
     
          var box1 = obj (box);    //相当于 var box1 = new F();
          alert(box1.name);         //   返回 Andy
          alert(box1.family);        //    返回 哥哥,姐姐
          box1.family.push(“弟弟”);
          alert(box1.family);        //    返回 哥哥,姐姐,弟弟
          var box2 = obj(box);
          alert(box2.family);        // 返回 哥哥,姐姐,弟弟
     
    因此,原型式继承的问题是包含引用类型值的属性始终会共享相应的值
     

    5、寄生式继承(原型式 + 工厂模式)
    例:function obj(o){                  //与原型式继承相同,临时中转函数
           function F(){}    
           F.prototype = o;  
           return new F();
            }
     
          function create(o){        //  创建寄生函数
           var f = obj(o);
            f.run = function(){
            return this.name+"方法";
            }
            return f ;
            }
     
    var box = {          
        name:”Andy",
        age:100,
        family:["哥哥","姐姐"]
      };
     
    var box1 = create(box);
    alert(box1.name)  //Andy
    alert(box1.run());  //Andy 方法
     
    此方法可以为对象添加函数,但也不能做到函数复用,与借用构造函数继承类似。
     

    6、寄生组合式继承
    function obj(o){
    function F( ){};
    F.prototype = o;
    return new F( ); 
     }
     
    function create(box,desk){
     var f = obj(box.prototype);
     f.constructor = desk;    //调整原型构造指针
    desk.prototype = f; 
    }
     
    function Box(name,age){
    this.name = name;
    this.age = age;
    }
    Box.prototype.run=function(){
       return  this.name+this.age +”启动”; 
    }
    function Desk(name,age){
      Box.call(this,name,age);    //对象冒充
    }
    create(Box,Desk);           //替代 Desk.prototype = new Box( );
    var desk = new Desk(“Andy”,28);
    alert(desk,run());    //弹出  Andy28启动
     
     
    问题:组合继承是 js 最常用的继承方式,但组合继承的超类型会在使用过程中会被调用两次,一次在创建子类型时,一次在子类型构造函数内部,即:Desk.prototype =  new Box( );第一次调用;Box.call(this,name,age);第二次调用。
    解决寄生组合式继承则解决了超类型被调用两次的问题
  • 相关阅读:
    React Native之通知栏消息提示(ios)
    前端知识点总结(HTML)
    React Native之通知栏消息提示(android)
    微信QQ打开网页时提示用浏览器打开
    微信小程序开发的基本流程
    React Native之code-push的热更新(ios android)
    ES7的新特性
    如何将本地项目上传到码云
    找不到或无法加载主类(Could not find or load main class)
    Java代码操作HDFS
  • 原文地址:https://www.cnblogs.com/emory/p/5034463.html
Copyright © 2020-2023  润新知