JavaScript 面向對象編程繼承 下【三】(instanceof,繼承和多重繼承)

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'
    
發佈了181 篇原創文章 · 獲贊 65 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章