继承

继承

  • 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,实现继承则继承实际的方法。由于ES中函数没有签名(也是无重载的原因),无法实现接口继承,只支持实现继承。
  • 原型链:利用原型让一个引用类型继承另一个引用类型的属性和方法。
  • 构造函数、原型和实例三者关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针

实现继承的方法

  • 父类

    //定义一个鸟类
    function Bird(name) {
    //属性
    this.name = name || 'Bird'
    //实例方法
    this.fly = function() {
    console.log(this.name + '正在飞!')
    }
    }
    //原型方法
    Bird.prototype.eat = function(food) {
    console.log(this.name + '正在吃' + food);
    };

  1. 原型链继承:将父类的实例作为子类的原型

    function Pigeon() {
    // 不能放到构造器
    }
    Pigeon.prototype = new Bird();
    Pigeon.prototype.name = 'Pigeon';
    //检测
    var pigeon = new Pigeon();
    console.log(pigeon.name);
    console.log(pigeon.fly());
    console.log(pigeon.eat(rice))

  • 缺点:
  1. 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
  2. 无法实现多继承
  3. 来自原型对象的引用属性是所有实例共享的,针对父类实例引用类型成员的更改,会通过影响其他子类实例
  4. 创建子类实例时,无法向父类构造函数传参
  1. 构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

    function Pigeon(name) {
    Bird.call(this);
    this.name = 'Pigeon' || name;
    }
    //检测
    var pigeon = new Pigeon();
    console.log(pigeon.name);
    console.log(pigeon.fly());//只能继承实例方法
    console.log(pigeon instanceof Bird);// false,不是父类的实例,只是子类的实例

  • 缺点:
  1. 实例并不是父类的实例,只是子类的实例
  2. 只能继承父类的实例属性和方法,不能继承原型属性/方法
  3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
  1. 组合继承:通过调用父类构造器,继承父类的属性并保留传参的有优点,然后将父类实例作为子类原型,实现函数复用

    function Pigeon(name) {
    Bird.call(this);//一份实例
    this.name = 'Pigeon' || name;
    }
    Pigeon.prototype = new Bird();//另一份实例
    Pigeon.prototype.constructor = Cat;//组合继承需要修复构造函数的指向
    //检测
    var pigeon = new Pigeon();
    console.log(pigeon.name);
    console.log(pigeon.fly());

  • 缺点:
  1. 调用了两次父类构造器,生成了两份实例
  1. 寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样在调用两次父类构造函数的时候,就不会初始化两次实例方法/属性,避免了组合继承的缺点

    function Pigeon(name) {
    Bird.call(this);
    this.name = 'Pigeon' || name;
    }
    (function() {
    // 创建一个没有实例方法的类
    var Super = function() {};
    Super.prototype = Bird.prototype;
    // 将实例作为子类的原型
    Pigeon.prototype = new Super();
    })();
    Pigeon.prototype.constructor = Pigeon;//修复指向构造函数的指针
    //测试
    var pigeon = new Pigeon();
    console.log(pigeon.name);
    console.log(pigeon.fly());
    console.log(pigeon.eat(rice));
    console.log(pigeon instance of Pigeon);/true
    console.log(pigeon instance of Bird);//true

posted @ 2018-03-23 14:53  YFIFE  阅读(168)  评论(0)    收藏  举报