精华内容
下载资源
问答
  • js组合继承和组合寄生继承 js设计之初是没有继承的概念的,如果要实现ES6中class A extends B的形式,需要借用prototype和Function.prototype.apply()方法或Function.prototype.call()方法。 原型链继承方式:B....

    js组合继承和组合寄生继承

    js设计之初是没有继承的概念的,如果要实现ES6中class A extends B的形式,需要借用prototypeFunction.prototype.apply()方法或Function.prototype.call()方法。

    • 原型链继承方式:B.prototype = A.prototype;,目的是继承父类方法
    • 构造函数继承方式:A.apply(this, arguments),目的是继承父类成员变量

    我们先看两个类

     // 父类
     var A = function(name){
         this.name = name;// 父类属性
     }
     // 父类方法
     A.prototype.setName = function(name){
        this.name = name
     }
     // 子类
     var B = function (){
         A.apply(this, arguments);// 继承属性
     }
     // 子类方法
     B.prototype.getName = function(){
         return this.name;
     }
    

    我们的目的是实现子类A继承父类B的属性name和方法setName(),并且B自有的属性和方法不能丢失

    1.组合继承

    将原型链继承和构造函数继承两种方式结合,apply()方法改变父类的this指向,prototype继承父类成员方法

    // 父类
    var A = function (name) {
        this.name = name;
    }
    A.prototype.setName = function (name) {
        this.name = name;
    }
    // 子类
    var B = function () {
        A.apply(this, arguments);// 将A的this指向B的this, 并且A接收B的构造函数参数
    }
    B.prototype = A.prototype;// 继承父类方法
    B.prototype.constructor = B;// 子类构造函数被覆盖掉了,恢复回来
    // 必须先写上面两行,才能给子类添加成员方法
    B.prototype.getName = function () {
        return this.name;
    }
    
    // 测试
    var b = new B('张三')
    b.setName('老刘')
    console.log('name=', b.getName())
    

    优缺点分析

    优点:

    • 写法简单,可满足基本使用

    缺点:

    • 1.顺序不能错。只能现将子类prototype执行父类的prototype,在增加子类原型方法。一旦顺序反了就会丢失子类自己的方法
    • 2.原型链上__proto__看不到父类,实际上只是把父类的属性和方法指向了子类,并不是真正的继承

    2.组合继承 + 寄生继承

    • 1.我们可以创建一个内部函数作为寄生母体var fun = function(){}
    • 2.让这个母体继承父类的原型fun.prototype = A.prototype
    • 3.再把寄生母体的contructor指向子类,fun.prototype.contructor = B
    • 4.创建寄生对象var obj = new fun(),这个obj没有任何属性,可以认为是个空对象,此时它的__proto__已经指向了A
    • 5.把子类B的原型链替换为上面常见的寄生对象objB.prototype = obj
    • 6.寄生继承完成,结束
    // 父类
     var A = function(name){
         this.name = name;// 父类属性
     }
     // 父类方法
     A.prototype.setName = function(name){
        this.name = name
     }
    // 调用此方法进行继承
    var _extends = function(sub, sup){
        // 寄生函数
        var fun = function(){ }
        fun.prototype = sup.prototype;// 原型链继承
        fun.prototype.contructor = sub;// contructor丢失,恢复
    
        sub.prototype = new fun();// 寄生函数创建的实例,里面只有原型链(__proto__)
    }
    // 子类
    var B = function (){
        A.apply(this, arguments);// 继承属性
    }
    _extends(B, A);
     // 子类方法
     B.prototype.getName = function(){
         return this.name;
     }
    
     var b = new B('张三')
     b.setName('李思')
     console.log(b.getName())
    

    优缺点分析

    优点:

    • 1.解决掉组合继承不是真正继承的毛病
    • 2.继承后的原型链比较清晰易懂

    缺点:

    • 额外增加一个寄生函数,占用更多内存

    参考资料

    展开全文
  • 组合寄生继承和class继承的区别

    千次阅读 2020-03-19 00:42:42
    先看下什么是原型继承 function object( o ){ var F = function(){}; F.prototype = o; return new F(); } var obj = { name : 'li', ...

    先看下什么是原型继承

            function object( o ){
                var F = function(){};
                F.prototype = o;
                return new F();
            }
            var obj = {
                name : 'li',
                age : 18,
                show : function(){
                    return this.name + ',' + this.age;
                }
            };
            var obj2 = object( obj );
            console.log( obj2.name, obj.age, obj.show() );

    在object中创建一个函数F,将F的原型指向参数o,并返回F函数的实例,这样就可以访问到对象o的所有属性和方法。缺点:由于是浅克隆,引用类型的数据共享在不同的实例之间。

    es5中新增了一个函数Object.create()来实现原型继承

    var obj = {
        "fruitList":["apple","orange"]
    }
    var obj2 = Object.create(obj);
    obj2.fruitList.push("banana");
    var obj3 = Object.create(obj);
    console.log(obj3.fruitList)

    寄生式继承

    寄生式继承就是把原型式继承再次封装,然后在对象上扩展新的方法,再把新对象返回

    function createAnother(original){
        var clone = Object.create(original);    //通过调用函数创建一个新对象
        clone.sayHi = function(){               //以某种方式来增强这个对象
            alert("Hi");
        };
        
        return clone;                        //返回这个对象
    }
    
    var person = {
        name: "Bob",
        friends: ["Shelby", "Court", "Van"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); //弹出 Hi

     

    展开全文
  • 从简单的层面深刻理解组合继承和寄生继承方式的由来 关于组合继承和寄生继承的文章已经很多了,但是多半都是将如何实现组合继承和组合继承的缺点,寄生继承的缺点的。 最近看到这篇文章,觉得很不错,思路清晰的,...

    从简单的层面深刻理解组合继承和寄生继承方式的由来

    关于组合继承和寄生继承的文章已经很多了,但是多半都是将如何实现组合继承和组合继承的缺点,寄生继承的缺点的。
    最近看到这篇文章,觉得很不错,思路清晰的,讲述了二者的由来,为什么需要用到组合继承,以及后续的基于组合继承的缺点发展出了寄生继承的方式。

    本文实例讲述了JavaScript寄生组合式继承。分享给大家供大家参考,具体如下:

    其实《JavaScript高级程序设计》这本书中已经有完整代码了,只要把代码读懂就知道这个继承是怎么回事。

    首先,在js中,给对象定义属性有两种方式:

        //通过执行构造函数设置属性
        function A(){
          this.a = 1;
        }
        //通过原型设置属性
        A.prototype.b = 1;
        所以:
    

    所以:
    一个类Sub要继承另一个类Super,需要继承父类的prototype下的属性,还要执行一下父类的构造函数。

    即一个类Sub要继承另一个类Super,既要通过原型链实现对原型属性和方法的继承,又要通过在子类构造函数内调用父类构造函数实现对实例属性的继承。

    1. 继承prototype下的属性

    上面可以看到,Super类的prototype下的属性是没有被继承的,因此下面还需要继承这一部分。

    直接「=」肯定不行,因为Sub.prototype中修改属性后,不能影响Super.prototype里面的对象,即不能Sub.prototype=Super.prototype

    首先写一个创建对象副本的方法

        function object(o){
          function A(){}
          A.prototype = o
          var ox = new A()
          return ox
        }
    

    上面的函数得到的对象ox,拥有了对象o的全部属性(在原型链上),而修改ox的属性,不会影响到o,相当于把o复制了一份。

    原型式继承就是上面的“object”函数,在很多类库源码中都能发现它的身影

    简单而言,原型式继承就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。即子类的原型指向父类副本的实例从而实现原型共享

    tips:总所周知,原型链继承是子类的原型指向父类的实例从而实现原型共享,而原型式继承是子类的原型指向父类副本的实例从而实现原型共享。

    ECMAScirpt 5通过新增Object.create()方法规范化了原型式继承。

    使用object方法,就可以将Super.prototype的属性「复制」到Sub.prototype上了,当然这儿还需要修正一下constructor的指向

    function inherit(subType,superType){
     var prototype=Object.create(superType.prototype);
     prototype.constructor=subType;
     subType.prototype=prototype;
    }
    

    2. 分别执行父类和子类的构造函数,继承这部分下的属性:

    //父类
    function Super(){
    this.sss=1
    }
    //子类
    function Sub(){
    //arguments是Sub收到的参数,将这个参数传给Super
    Super.apply(this, arguments)
    }
    //实例
    sub = new Sub()
    

    Super.apply(this, arguments)这一句,将Super类作为一个普通函数来执行,但是Super类的this被换成了Sub类的this,Sub收到的参数也传给了Super

    最后执行结果相当于sub.sss=1

    附上各种继承方式的特点和优缺点

    曾经一段时间因为javascript关于类实现继承的不规范,导致各种各样实现继承的代码;而实际上不管代码怎么变,继承都基于两种方式:

    1.通过原型链,即子类的原型指向父类的实例从而实现原型共享。
    2.借用构造函数,即通过js的apply、call实现子类调用父类的属性、方法;

    原型链方式可以实现所有属性方法共享,但无法做到属性、方法独享(例如Sub1修改了父类的函数,其他所有的子类Sub2、Sub3…想调用旧的函数就无法实现了);

    借用构造函数除了能独享属性、方法外还能在子类构造函数中传递参数,但代码无法复用。总体而言就是可以实现所有属性方法独享,但无法做到属性、方法共享(例如,Sub1新增了一个函数,然后想让Sub2、Sub3…都可以用的话就无法实现了,只能Sub2、Sub3…各自在构造函数中新增)。

    组合继承就是把以上两种继承方式一起使用,把共享的属性、方法用原型链继承实现,独享的属性、方法用借用构造函数实现,所以组合继承几乎完美实现了js的继承;为什么说是“几乎”?因为认(dan)真(teng)的geek们发现组合继承有一个小bug,实现的时候调用了两次超类(父类),性能上不合格啊有木有!怎么解决呢?于是“寄生继承”就出来了。

    寄生继承(原型式继承)就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)

    “寄生组合继承”用了“寄生继承”修复了“组合继承”的小bug,从而让js完美实现继承了。

    实例代码:

    function SuperType(name,colors){
      this.name=name;
      this.colors=colors;
    }
    SuperType.prototype.getSuperProperty=function(){ return this.name; }
    function SubType(job,name,colors){
      SuperType.call(this,name,colors);
      this.job=job;
    }
    SubType.prototype.getSubPrototype=function(){ return this.job; }
    function inherit(subType,superType){
      var prototype=Object.create(superType.prototype);
      prototype.constructor=subType;
      subType.prototype=prototype;
    }
    inherit(SubType,SuperType);
    var instance=new SubType("doctor","John",["red","green"]);
    console.log(instance.getSubPrototype());  //输出"doctor"
    console.log(instance.getSuperProperty());  //输出"John",成功调用在父类原型定义的方法
    

    属性继承代码是SuperType.call(this,name,colors);

    原型继承代码是inherit(SubType,SuperType);

    原文链接:http://blog.csdn.net/qq_26222859/article/details/77508778

    展开全文
  • 寄生组合继承

    千次阅读 2019-04-20 10:55:40
    寄生组合继承
  • 下面小编就为大家带来一篇浅谈JS继承_寄生继承 & 寄生组合继承。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了JavaScript寄生组合继承,结合实例形式详细分析了寄生组合继承原理、实现方法与相关注意事项,需要的朋友可以参考下
  • javascript组合继承寄生组合继承 javascript组合继承 组合继承式javascript最常见的继承模式;不过他也有自己的不足。组合继承最大的问题就是无论在什么情况下都会调用两次超类型构造函数: 一次是在创建...
  • 这里着重记录一下组合继承和寄生继承的区别 组合继承 function Person(name) { this.name = name, this.age = '23' } Person.prototype.sayName = function(){ console.log('my name is'+this.name+'.'); } ...
  • 寄生组合继承

    2021-10-01 22:14:55
    寄生组合继承 结合原型链继承和call继承的方法,同时自己创建一个对象,并且让这个对象的原型指向父类构造函数的prototype.实现寄生组合继承。 function Parent(x) { this.x = x this.Hello = function () { }...
  • 因为这三种实现继承的方式都是有关联的,所以将他们放在一起了(其实可以将原型链继承也放进来)。 一、借用构造函数实现继承 二、组合继承 三、寄生组合继承
  • /* 组合继承*/function Parent(){ this.name='wsq'; this.sex='nan'; this.sleep=function(){ alert("success"); }};Parent,prototype.eat=function(){ alert("yes");}; function Clild(name){ Parent.call(this);...
  • 主要介绍了JavaScript寄生组合继承,结合实例形式分析了javascript寄生组合继承的原理、定义与简单使用方法,需要的朋友可以参考下
  • 组合继承(伪经典继承) 组合继承综合了原型链和盗用构造函数,解决了原型内引用值共享的问题,以及子类在实例化时不能给父类构造函数传参的问题。 缺点: 调用了两次父类构造函数影响效率,而且子类的...寄生组合继承
  • JS基础--组合继承寄生组合继承

    千次阅读 2019-05-13 17:03:29
    组合继承使用原型链实现对原型属性和方法的继承,使用借用构造函数实现对实例属性的继承(引用类型的属性写在构造函数里)。 示例: function SuperType (name) { this.name = name; this.colors = ["red", "green...
  • Javascript继承通常有三种方式。...第一种:组合继承: function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function() { ...
  • js寄生组合继承示例

    2018-06-14 13:45:24
    JavaScript寄生组合继承实现代码示例
  • 关于javascript中的组合寄生寄生组合继承的理解目录什么是继承寄生继承组合继承寄生组合继承总结 目录 什么是继承 继承是让子类获得父类的属性和方法,或者可以重新定义属性和方法 寄生继承 如何实现...
  • * 寄生组合继承: * 使用寄生继承继承超类型的原型,然后将结果指定给子类型的原型 * 优点:高效率,它只调用了一次Supertype构造函数,避免了在prototype上面创建不必要的多余属性, * 同时,原型链还能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,061
精华内容 2,824
关键字:

组合寄生继承