JavaScript 面向对象编程继承 下【三】(instanceof,继承和多重继承)

  • A+

JavaScript 是一门集成了函数编程和面向对象编程的动态语言。它的对象是一个容器,封装了属性(property)和方法(method)。JavaScript的面向对象实现不是基于类,而是基于构造函数(constructor)和原型链(prototype)实现的。

一.概述

  1. 本文主要介绍了instanceof属性,继承和多重继承。
  2. instanceof运算符介绍? instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。关键字左边是实例,右边是构造函数。检测原理是:检查右边构造函数的prototype属性,是否在左边对象的原型链上。具体见: instanceof 运算符
  3. 继承和多重继承介绍? 继承有2种写法,第一种写法是在子类构造函数中,调用父类的构造函数。并且将子类的原型对象修改为父类的原型。第二种写法,子类的原型直接指向父类的一个匿名实例。具体见: 构造函数的继承

二.instanceof 运算符

1.概念

  • 概念instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例。
  • 概念instanceof运算符的左边是实例对象,右边是构造函数。instanceof的原理是检查右边构造函数的prototype属性,是否在左边对象的原型链上。
    //一. 左边实例右边构造函数
    var v = new Vehicle();
    v instanceof Vehicle // true
    
    //二. 检查Vehicle的prototype是否在v实例的原型对象的原型链上
    v instanceof Vehicle
    // 等同于
    Vehicle.prototype.isPrototypeOf(v)
    
    //三. instanceof 检查的是原型链,同一个实例对象,多个构造函数都返回true
    var d = new Date();
    d instanceof Date // true
    d instanceof Object // true
    

2.使用

  • 使用:判断一个值是否为null对象。由于任意对象(除了null)都是Object的实例。
    var obj = { foo: 123 };
    obj instanceof Object // true
    
    null instanceof Object // false
    
  • 使用:判断值的类型
    var x = [1, 2, 3];
    var y = {};
    x instanceof Array // true
    y instanceof Object // true
    
  • 使用:利用instanceof运算符,还可以巧妙地解决,调用构造函数时,忘了加new命令的问题。
    function Fubar (foo, bar) {
      if (this instanceof Fubar) {
        this._foo = foo;
        this._bar = bar;
      } else {
        return new Fubar(foo, bar);
      }
    }
    

3.注意

  • 注意:instanceof判断会失真,在左边对象的原型链上,只有null对象。这时就会出现失真。
    //Object.create(null)返回一个新对象obj,它的原型是null
    var obj = Object.create(null);
    typeof obj // "object"
    Object.create(null) instanceof Object // false
    
  • 注意instanceof运算符只能用于对象,不适用原始类型的值。总返回false。对于undefinednullinstanceof运算符总是返回false。

三.构造函数的继承

1.构造函数的单继承

  • 写法:让一个构造函数继承另一个构造函数,第一种写法是在子类构造函数中,调用父类的构造函数。并且将子类的原型对象修改为父类的原型
    //一. 第一步,子类的构造函数调用父类构造函数
    function Sub(value) {
      Super.call(this);
      this.prop = value;
    }
    //二. 第二步,是让子类的原型指向父类的原型
    Sub.prototype = Object.create(Super.prototype);
    Sub.prototype.constructor = Sub;
    Sub.prototype.method = '...';
    
  • 写法:第二种写法, 子类的原型直接指向父类的一个匿名实例
    Sub.prototype = new Super();
    
  • 范例一,构造函数整体继承父类:
        //一. 定义父类构造函数,并在原型对象上添加move方法
        function Shape() {
          this.x = 0;
          this.y = 0;
        }
    
        Shape.prototype.move = function (x, y) {
          this.x += x;
          this.y += y;
          console.info('Shape moved.');
        };
    
        //二. 执行继承
        // 第1步,子类继承父类的实例
        function Rectangle() {
          Shape.call(this); // 调用父类构造函数
        }
    
        // 第2步,子类继承父类的原型
        Rectangle.prototype = Object.create(Shape.prototype);
        Rectangle.prototype.constructor = Rectangle;
    
        //三. 验证
        var rect = new Rectangle();
    
        rect instanceof Rectangle  // true
        rect instanceof Shape  // true
    
  • 范例二,继承父类的单个方法:
    ClassB.prototype.print = function() {
      ClassA.prototype.print.call(this);
      // some code
    }
    

2.多重继承

  • JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能。
    function M1() {
      this.hello = 'hello';
    }
    
    function M2() {
      this.world = 'world';
    }
    
    function S() {
      M1.call(this);
      M2.call(this);
    }
    
    // 继承 M1
    S.prototype = Object.create(M1.prototype);
    // 继承链上加入 M2
    Object.assign(S.prototype, M2.prototype);
    
    // 指定构造函数
    S.prototype.constructor = S;
    //子类S同时继承了父类M1和M2。这种模式又称为 Mixin(混入)
    var s = new S();
    s.hello // 'hello'
    s.world // 'world'
    
zhangfeng

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: