[譯] JavaScript — 繼承、委託模式和對象連接

原文地址: JavaScript — Inheritance, delegation patterns and Object linkingjavascript

做者: NC Patrojava

學習 JavaScript (原型繼承) 中的繼承,行爲/對象委託模式和關聯到其它對象的對象函數

什麼是繼承

在大多數基於類的面嚮對象語言中,繼承是一種讓一個對象能夠得到另外一個對象全部的屬性和方法的機制。雖然在 ES2015 中 提出了 class 關鍵字,但 JavaScript 並非一門基於類的語言,它僅僅只是語法糖,本質上仍是原型鏈的方式。工具

經典繼承與原型繼承

經典繼承(非 JavaScript)

  • Vehicle 是父類,v1 v2Vehicle 的實例。
  • CarVehicle 的子類而 c1c2Car 的實例。
  • 當咱們繼承類時,經典繼承建立了一個來自父類行爲的拷貝到子類中,而後父子類就是獨立的實體了。
  • 這就像是汽車是用工具以及汽車圖紙造出來的,但造完之後二者都是獨立的個體,由於它就是一份拷貝因此它們之間沒有關聯,這就是全部箭頭向下(屬性和行爲向下傳遞)的緣由。

原型繼承(行爲委託模式)

  • v1v2 關聯到 Vehicle.prototype 由於它們是經過 new 建立的。
  • 一樣的,c1c2 關聯到 Car.prototypeCar.prototype 關聯到 Vehicle.prototype
  • JavaScript 中當咱們建立一個對象時,它不是複製屬性或者行爲,而是建立一個連接. 在繼承一個類時也會建立相似的連接。
  • 與經典的非 JavaScript 繼承相比,全部連接向着相反的方向,由於它是行爲委託連接。 這些連接稱爲原型鏈
  • 這個模式稱爲行爲委託模式,一般稱爲 JavaScript 中的 原型繼承

你能夠經過這篇文章 JavaScript-原型 去深刻理解 原型鏈post

原型繼承的例子

  • 使用 Object.create() 實現經典繼承。
  • 在下列代碼片斷中,Car.prototypeVehicle.prototypeObject.create() 函數的幫助下相鏈接。
// Vehicle - 超類
function Vehicle (name) {
    this.name = name;
}
// 超類的方法
Vehicle.prototype.start = function () {
    return "engine of " + this.name + " starting...";
}

// Car - 子類
function Car (name) {
    Vehicle.call(this, name); // 調用超類的構造函數
}
// 子類擴展超類
Car.prototype = Object.create(Vehicle.prototype);
// 子類的方法
Car.prototype.run = function () {
    console.log("Hello " + this.start());
}

// 子類的實例
var c1 = new Car("Fiesta");
var c2 = new Car("Baleno");

// 訪問 內部訪問了超類方法 的子類方法
c1.run();   // "Hello engine of Fiesta starting..."
c2.run();   // "Hello engine of Baleno starting..."
複製代碼
  • 在上述代碼中,因爲下面的原型鏈,對象 c1 能夠訪問到 run() 方法和 start() 方法. 以下圖所示,咱們能夠看到 c1 沒有這樣的方法,但它有向上的連接。
  • 上面代碼中的 this 只不過是每一個方法當前的執行上下文,即 c1c2

你能夠瀏覽這篇文章 JavaScript-關於 this 和 new 的全部內容 來詳細瞭解 this 關鍵字學習

上述代碼的圖解表示:ui

與其它對象關聯的對象

  • 如今咱們將會簡化先前的繼承示例代碼,只關注對象與對象之間的連接。
  • 因此咱們將會嘗試移除 .prototypeconstructornew 關鍵字,只考慮對象。
  • 咱們將會使用 Object.create() 函數來建立函數之間的全部連接。

下面是先前示例代碼的簡化版:this

// 包含初始化方法的基礎對象
var Vehicle = {
    init: function (name) {
        this.name = name;
    },
    start: function () {
        return "engine of " + this.name + "starting...";
    }
}

// 在子對象和基礎對象之間建立的委託連接
var Car = Object.create(Vehicle);

// 子對象的方法
Car.run = function () {
    console.log("Hello " + this.start());
};

// 具備委託連接的實例對象指向子對象
var c1 = Object.create(Car);
c1.init('Fiesta');

var c2 = Object.create(Car);
c2.init('Baleno');

c1.run();   // "Hello engine of Fiesta starting..."
c2.run();   // "Hello engine of Baleno starting..."
複製代碼

上述代碼的圖解展現spa

  • 如今咱們能夠看到,咱們如何消除了 new ,全部 .prototype ,構造函數和調用方法的複雜性,而且仍然實現了相同的結果。
  • 惟一重要的是 c1 連接到一個對象而後再連接到另外一個對象,依次類推。
  • 這也被稱做對象委託模式。

總結

爲了規避複雜性,在代碼中使用原型繼承與原型鏈前先理解它們是很重要的。prototype

參考: You Don't Know JS 系列叢書

相關文章
相關標籤/搜索