JS類與繼承

一些概念

prototype是構造函數的指針,指向原型對象。講述的是構造函數和原型對象之間的關系。
__proto__是實例對象的指針,也指向原型對象,講述的是實例對象和原型對象之間的關系。
因為原型對象也是對象,所以原型對象也有__proto__,指向的是這個原型對象的原型對象,JS實現繼承的方式就是根據__proto__指針,在一個對象上查找一個property,會依次在自身對象、原型對象、原型對象的原型對象(就是原型鏈)。
所以在js中實現繼承的關鍵就是使得一個原型對象的__proto__指針指向某一個(原型)對象。

最后在說一下constructor指針。
constructor是原型對象的的指針,指向構造函數。講述的是原型對象和構造函數之間的關系。所以和prototype是互逆的一對指針。

《《JavaScript高級程序設計》》第三版講解原型和繼承對于有些基礎的人有些拖沓。其中第六章第三節講解繼承的時候也告訴了在JavaScript實現繼承的業界默認方式就是借用構造函數和原型繼承。

其背后的思路就是使用原型鏈實現對原型屬性和方法的繼承,通過借用構造函數來實現對實例屬性的繼承。

上面這句話總結的很好很全面了。

所以繼承包括兩個方面,實例屬性和原型屬性的繼承。

繼承實例屬性最常用的一種方法是上面說到的借用構造函數。

function ParentClass() { // 父類構造函數
}

function ChildrenClass(xx,yy,zz) { // 子類構造函數
  ParentClass.call(this,xx,yy);
  this.zz = zz;
}

繼承原型屬性的方法就有很多種了。

Object.create

function inherit(C,P) {
  C.prototype = Object.create(P.prototype)
}

inherit(ChildrenClass,ParentClass)

最早老道提出來這種方法叫原型式繼承。實現了一個create方法,只不過ES5在語法層面實現了create方法,形成了上面的方法。

function create(o) {
  var F = new Function();
  F.prototype = o;
  return new F();
}

function inherit(C,P) {
  C.prototype = create(P.prototype)
}

inherit(ChildrenClass,ParentClass)

原型式繼承之二

function inherit(C,P) {
    var F = new Function();  // 臨時構造函數
    F.prototype = P.prototype;
    C.super = P; // 使得子類能夠獲得對父類的引用
    C.prototype = new F(); // 使得子類的原型對象__proto__指向父類的原型對象,從而實現繼承原型方法
    C.prototype.constructor = C; // 使得子類的constructor指針重新指向子類的構造函數
}

inherit(ChildrenClass,ParentClass)

setPrototypeOf

const inherit = function(ctor, superCtor) {

  if (ctor === undefined || ctor === null)
    throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'ctor', 'function');

  if (superCtor === undefined || superCtor === null)
    throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'superCtor', 'function');

  if (superCtor.prototype === undefined) {
    throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'superCtor.prototype',
                               'function');
  }
  ctor.super_ = superCtor;
  Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
};

上面一段代碼來自node的util模塊的inherits方法。使用了ES6的Object.setPrototypeOf.
其實都ES6了,為什么不直接使用ES6的extends關鍵字。

ES6

ES6的到來,為JS實現了語言層面的class。其實也只是上面內容的一個語法糖。即使在各種環境都支持ES6和class的情況下,熟悉和了解JS中繼承是如何實現的也是很有必要的。
詳細的ES6 class講解可以參考 阮一峰的ES6教程;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 博客內容:什么是面向對象為什么要面向對象面向對象編程的特性和原則理解對象屬性創建對象繼承 什么是面向對象 面向對象...
    _Dot912閱讀 1,447評論 3 12
  • 理解 javascript 的原型鏈及繼承 以上所有的運行結果都是 true; 三種構造對象的方法: 通過對象字面...
    你期待的花開閱讀 1,537評論 0 3
  • 1,javascript 基礎知識 Array對象 Array對象屬性 Arrray對象方法 Date對象 Dat...
    Yuann閱讀 945評論 0 1
  • 看到水田里茁長成長的禾苗,田田的翠翠的煙葉,不由得想起了被我擱置心里快要遺忘的童年和少年。 ...
    潤秀閱讀 235評論 0 0
  • 我是日記星球215號星寶寶王小鳳,正在參加小牛媽媽日記星球21天蛻變之旅的寫作訓練,這是我的第37篇原創日記。 忍...
    小鳳Isabel閱讀 320評論 0 2