美文网首页
JS | 构造函数的继承

JS | 构造函数的继承

作者: 灬劣徒 | 来源:发表于2019-04-29 11:35 被阅读0次
    //定义两个构造函数
    function Animal() {
      this.species = '动物';
    }
    
    function  Cat(name.color) {
      this.name = name;
      this.color = color;
    }
    

    &&&

    1.使用call和apply方法

    这种方法是最简单的方法,使用call和apply方法,.把父对象的构造函数绑定在子对象上

    Animal.apply(this,arguments) 或 Animal.call(this,name,color)

    function Cat(name,color) {
      Animal.apply(this,arguments);
      this.name = name;
      this.color = color;
    }
    let cat = new Cat('大毛','黄色');
    cat.species;  // '动物'
    

    2.原型式继承

    这种是最常见的,把一个构造函数的prototype,指向另一个构造函数的实例

    Cat.prototype = new Animal();
    Cat.prototype.constructor = Cat; //这种方式丢失了原来的constructor属性,所以要手动纠正
    let cat = new Cat('二毛','绿色');
    cat.species;  // '动物'
    
    //每一个实例也有constructor属性,默认调用prototype属性的constructor
    cat.constructor = Cat.prototype.constructor;  // true
    

    3.直接继承prototype

    这种方法是对上一种方法的改进.在Animal对象中,共用的属性都可以写入Animal.prototype,所以我们也可以让Cat() 跳过Animal(),直接继承Animal.prototype

    //先改写Animal的prototype属性
    function Animal() {}
    Animal.prototype.species = '动物';
    Cat.prototype = Animal.prototype;
    Cat.prototype.constructor = Cat;
    let cat = new Cat('三毛','蓝色');
    cat.species = '动物';
    

    优点:与上一种方法相比,这样做的效率比较高(不用创建Animal的实例了),比较节省内存.
    缺点:因为Cat.prototype和Animal.prototype都指向同一个对象,那么任何对Cat.prototype的修改,都会反应到Animal.prototype

    4.利用空对象作为中介

    直接继承prototype存在上述缺点,所以就有了第四种写法,利用一个空对象作为中介

    function F(){}
    F.prototype = Animal.prototype;
    Cat.prototype = new F();
    Cat.prototype.constructor = Cat;
    
    //这时,修改Cat.prototype对象就不会影响到Animal.prototype 
    Animal.prototype.constructor; // Animal
    

    把上面这种形式封装成一个方法,便于使用

    function extend(Child,Parent) {
      let F = function() {};
      F.prototype = Parent.prototype;
      Child.protype = new F;
      Child.prototype.constructor = Child;
      Child.uber = Parent.prototype;
    }
    

    这个extend方法,就是YUI库如何实现继承的方法

    另外,特别说明一点,函数体最后一行代码 Child.uber = Parent.prototype
    意思是为子对象设置一个uber属性,这个属性直接指向父对象的prototype(uber德语的意思是'向上','上一层'),这等于在子对象上打开了一条通道,可以直接调用父对象上的方法.这一行放在这里,只是为了继承的完备性,纯属备用性质

    5.拷贝继承

    上面是利用了prototype对象实现了继承.我们也可以换一种思路,纯粹采用'拷贝'实现继承.简单说,就是把父对象上的所有属性和方法,都拷贝到子对象身上,这样不也能够实现继承吗

    首先还是把Animal身上所有的共用方法,都放到prototype上

    function Animal(){} 
    Animal.prototype.species = '动物';
    

    接下来是继承方法,实现属性拷贝

    function extend(Child,Parent) {
      let p = Parent.prototype;
      let c = Child.prototype;
      for(let i in p) {
        c[i] = p[i];
      }
      c.uber = p.prototype;
    }
    

    这个对象的目的,就是把Parent.prototype上的属性,逐一拷贝给Child.prototype

    原文摘自JS 面向对象编程(二)

    相关文章

      网友评论

          本文标题:JS | 构造函数的继承

          本文链接:https://www.haomeiwen.com/subject/gzpenqtx.html