• javascript实现继承3种方式: 原型继承、借用构造函数继承、组合继承,模拟extends方法继承


     javascript中实现继承的三种方式:原型继承、借用构造函数继承、混合继承:

      1 /*
      2     js当中的继承
      3     
      4     js中 构造函数 原型对象 实力对象的关系:
      5         1 构造函数.prototype = 原型对象
      6         2 原型对象.constructor = 构造函数(模板)
      7         3 原型对象.isPrototypeOf(实例对象)  判断实例对象的原型是不是当前对象
      8         4 构造函数 实力对象 是 类和对象的关系            
      9 */
     10 
     11 
     12 /*
     13 1 原型继承
     14         给子类构造函数的原型对象赋值为父类构造函数的实例
     15     赋值之后产生的关系:
     16         1 子类的原型对象是父类的一个实例   Son.prototype 是 new Father()
     17         2 父类的方法和属性,子类可以在原型中得到    
     18         3 子类的原型对象的构造器是父类模板    Son.prototype.constructor 是 Father
     19         4 子类的原型对象的原型对象是父类的原型对象    Son.prototype.prototype 是Father.prototype
     20     原型继承的特点:
     21         子类继承了父类所有属性方法发和 父类原型对象中的属性和方法
     22     缺点: 不能在子类实例化对象的时候给父类的属性赋值,继承父类的值和子类对象实例化分开了。
     23 */
     24 
     25 //父类构造函数
     26 function Father(name){
     27     this.name = name;
     28 }
     29 //父类原型对象
     30 Father.prototype={
     31     constructor: Father,
     32     id:10,
     33     sayName:function(){
     34         alert(this.name);
     35     }
     36 };
     37 
     38 //子类构造函数
     39 function Son(age){
     40     this.age = age;
     41 }
     42 //子类原型对象 这一家子都姓张
     43 Son.prototype = new Father("张");
     44 
     45 //子类的实例 能够使用父类的属性和方法
     46 var s1 = new Son(18);
     47 //s1.sayName();    //张
     48 //alert(s1.age);    //18        
     49 
     50 /*
     51     原型继承的特点:
     52         子类继承了父类所有属性方法发和 父类原型对象中的属性和方法
     53     缺点: 不能在子类实例化对象的时候给父类的属性赋值,继承父类的值和子类对象实例化分开了。
     54 */
     55 
     56 
     57 
     58 
     59 /*
     60 2 类继承(借用构造函数) 只继承父类的构造函数,父类的原型对象没有继承过来
     61     利用call 或者apply进行函数绑定,借用父类构造函数的属性和方法
     62 */
     63 //父类构造函数
     64 function Father(name){
     65     this.name = name;
     66 }
     67 //父类原型对象    在子类中不能继承父类原型对象中的内容
     68 Father.prototype.id = 10;
     69 
     70 //子类构造函数
     71 function Son(name,age){
     72     //name属性是父类的 不是子类的 借用父类的构造函数 把属性绑定给子类的实例对象
     73     Father.call(this,name);
     74     this.age = age;
     75 }
     76 //实例化子类对象 在这里可以直接给继承来的属性赋值
     77 var s2 = new Son("z3",18);
     78 //alert(s2.name);    //z3  父类构造函数绑定来的属性
     79 //alert(s2.age);    //18  子类自己的属性
     80 
     81 /*
     82     类继承(借用构造函数) 的特点:
     83         优点: 能够在实例化子类对象时候给继承父类的属性赋值
     84         缺点:父类的原型对象中的内容无法继承
     85 */
     86 
     87 
     88 /*
     89 3 混合继承:原型继承 和 借用构造函数继承 的混合
     90     特点:
     91         优点:1 能够在实例化子类对象的时候给继承来的属性赋值
     92                2 能够继承父类的原型对象中的方法
     93         缺点: 继承了两次父类的模版,分别是call绑定和子类原型对象赋值的时候
     94                 如果继承来的属性特别多,这会很耗费时间来维护
     95 */
     96 //父类
     97 function Father(name){
     98     this.name = name;
     99 }
    100 //父类的原型对象
    101 Father.prototype = {
    102     constructor:Father,
    103     id:10,
    104     sayName:function(){
    105         alert(this.name);
    106     }
    107 };
    108 //子类
    109 function Son(name,age){
    110     //借用父类构造函数 绑定子类方法 为子类继承来的属性赋值
    111     Father.call(this,name);
    112     this.age = age;
    113 }
    114 //原型继承 不传递参数,继承自父类的属性赋值交给借用父类构造函数去做
    115 Son.prototype = new Father();
    116 
    117 //使用子类实例化对象
    118 var s3 = new Son("l4",20);
    119 //alert(s3.name);    //父类属性
    120 //alert(s3.id);    //父类原型对象的属性
    121 //alert(s3.age);    //自己的属性
    122 //s3.sayName();    //父类原型对象中的方法
    123 /*
    124     混合集成的特点:
    125         优点:1 能够在实例化子类对象的时候给继承来的属性赋值
    126                2 能够继承父类的原型对象中的方法
    127         缺点: 继承了两次父类的模版,分别是call绑定和子类原型对象赋值的时候
    128                 如果继承来的属性特别多,这会很耗费时间来维护
    129 */

    但是 上面三种方式 即使是混合继承也有弊端,下面用js模拟一下extends的继承方,来实现不会重复继承父类的构造函数:

     1 /*
     2 javascript模拟extends方法,
     3     目的:
     4         1子类实例化能够赋值继承来的属性   
     5         2 继承父类的原型对象    
     6         3 父类的构造函数只继承一次
     7 */
     8 
     9 //1 我们模拟一个extends函数 用于实现类之间的继承 传入父类和子类
    10 function extend(son,father){
    11     //让子类继承父类的原型而不继承父类构造函数的内容
    12     var f = new Function(); //临时空函数,目的是函数内部是空的 但是原型是父类的原型
    13     f.prototype = father.prototype;    //让空函数的原型指向父类的原型
    14     son.prototype = new f();    //让子类的原型指向一个空函数,空函数的原型是父类的原型,这就避免了父类构造函数的属性被重复实现
    15     //给子类添加一个superClass属性保存父类的原型对象,防止自己重写了父类方法后 无法调用父类原型对象中的方法
    16     son.superClass = father.prototype;
    17     //为父类原型对象添加构造器  如果父类原型对象忘记加构造器这里给他加上
    18     if(father.prototype.constructor == Object.prototype.constructor){
    19         father.prototype.constructor = father;
    20     }
    21 }
    22 //2 父类
    23 function Father(name){
    24     this.name = name;
    25 } 
    26 //父类的原型对象
    27 Father.prototype = {
    28     constructor: Father,
    29     sayName:function(){
    30         alert(this.name);
    31     }
    32 };
    33 
    34 
    35 //3 子类
    36 function Son(name,age){
    37     //借用构造函数:为子类绑定父类的构造函数中属性
    38     // Father.call(this , name); 这里不这样写,为了解耦,增加通用性,经过extentds函数之后,子类里面有了父类的属性
    39     Son.superClass.constructor.call(this , name);    //Son.superClass是父类的原型对象,consturctor就是父类构造函数
    40     this.age = age;
    41 }
    42 //原型继承    
    43 //Son.prototype = new Father(); //会再次绑定一次父类的构造函数 ,这里为了不重复继承父类构造函数,只继承父类原型对象 我们用自己
    44 //调用自己的继承方法 实现为子类继承父类的原型对象 而不继承父类的构造函数
    45 
    46 
    47 
    48 extend(Son,Father);
    49 
    50 
    51 
    52 //使用子类
    53 var s4 = new Son("haha",33);
    54 alert(s4.name);    //haha 父类继承来的属性
    55 alert(s4.age);    //33 自己的属性
    56 s4.sayName();    //haha  父类继承来的方法
    57 //重写父类方法
    58 s4.sayName = function(){
    59     alert("hello i am son");
    60 };
    61 s4.sayName();    //hello i am son 重写方法覆盖了父类的sayName
    62 //重写之后还想调用父类的方法    需要绑定一下 指定是我这个对象来调用
    63 Son.superClass.sayName.call(s4);    //haha
    64     
    65     
    66     
  • 相关阅读:
    Sql的同一机器不同数据库联合查询示例
    poi 公式自動重新計算
    js 取得文件大小
    java 读写文件
    Postman安装及入门实践(以百度搜索为例)
    PostmanTests模块测试方法记录
    HTML颜色代码
    网盘搜索器 v1.0
    线程知识点一:如何传入多个参数
    asp.net 实现省市级联<简单方法2>前台实现
  • 原文地址:https://www.cnblogs.com/Lin-Yi/p/7446841.html
Copyright © 2020-2023  润新知