javascript原型繼承(第二篇)---繼承的設計思想

最初接觸javascript,讓我有一種感覺——javascript 原型繼承到底講的是什麼? 看了很多關於Javascript原型繼承的資料,仍舊弄不懂它要講什麼,不過今天在看了一篇博客後,頓時讓我有種醍醐灌頂的感覺,下面就將這篇博客的內容貼出來。

javascript 沒有”子類”和”父類”的概念,也沒有”類”(class)和”實例”(instance)的區分,全靠一種很奇特的”原型鏈”(prototype chain)模式,來實現繼承

一、 javascript的歷史來源

1994年,網景公司(Netscape)發佈了Navigator瀏覽器0.9版,但是,這個版本的瀏覽器只能用來瀏覽,不具備與訪問者互動的能力,因此,網景公司急需一種網頁腳本語言,使得瀏覽器可以與訪問者互動。工程師Brendan Eich負責開發這種新語言。他覺得,沒必要設計得很複雜,因爲畢竟是一種腳本語言。

正是面向對象編程(object-oriented programming)最興盛的時期,C++是當時最流行的語言,而Java語言的1.0版即將於第二年推出。Brendan Eich無疑受到了影響,Javascript裏面所有的數據類型都是對象(object),這一點與Java非常相似。但是,他隨即就遇到了一個難題,到底要不要設計”繼承”機制呢?

二、Brendan Eich的選擇

如果真的是一種簡易的腳本語言,其實不需要有”繼承”機制。但是,Javascript裏面都是對象,必須有一種機制,將所有對象聯繫起來。所以,Brendan Eich最後還是設計了”繼承”。

但是,他不打算引入”類”(class)的概念,因爲一旦有了”類”,Javascript就是一種完整的面向對象編程語言了,這好像有點太正式了,而且增加了初學者的入門難度。

他考慮到,C++和Java語言都使用new命令,生成實例。

因此,他就把new命令引入了Javascript,用來從原型對象生成一個實例對象。但是,Javascript沒有”類”,怎麼來表示原型對象呢?

他想到C++和Java使用new命令時,都會調用”類”的構造函數(constructor)。他就做了一個簡化的設計,在Javascript語言中,new命令後面跟的不是類,而是構造函數。

舉例來說,現在有一個叫做DOG的構造函數,表示狗對象的原型。

function DOG(name){
    this.name = name;
  }

對這個構造函數使用new,就會生成一個狗對象的實例。

var dogA = new DOG('大毛');
  alert(dogA.name); // 大毛
三、new操作符的缺點

用構造函數生成實例對象,有一個缺點,那就是無法共享屬性和方法。

比如,在DOG對象的構造函數中,設置一個實例對象的共有屬性species。

function DOG(name){
    this.name = name;
    this.species = '犬科';
  }

然後,生成兩個實例對象:

var dogA = new DOG('大毛');
var dogB = new DOG('二毛');

這兩個對象的species屬性是獨立的,修改其中一個,不會影響到另一個。

每一個實例對象,都有自己的屬性和方法的副本。這不僅無法做到數據共享,也是資源的浪費。

四、prototype屬性的引入

考慮到這一點,Brendan Eich決定爲構造函數設置一個prototype屬性。
這個屬性包含一個對象(以下簡稱”prototype對象”),所有實例對象需要共享的屬性和方法,都放在這個對象裏面;那些不需要共享的屬性和方法,就放在構造函數裏面。

實例對象一旦創建,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法,分成兩種,一種是本地的,另一種是引用的。(也可以說,一種是共享的,一種是不需要共享的。)

以DOG構造函數爲例,現在用prototype屬性進行改寫:

function DOG(name){
    this.name = name;
  }
  DOG.prototype = { species : '犬科' };

  var dogA = new DOG('大毛');
  var dogB = new DOG('二毛');

  alert(dogA.species); // 犬科
  alert(dogB.species); // 犬科

現在,species屬性放在prototype對象裏,是兩個實例對象共享的。只要修改了prototype對象,就會同時影響到兩個實例對象。

   DOG.prototype.species = '貓科';

   alert(dogA.species); // 貓科
   alert(dogB.species); // 貓科

由於所有的實例對象共享同一個prototype對象,那麼從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像”繼承”了prototype對象一樣。

這就是Javascript繼承機制的設計思想。


第三篇: javascript原型繼承(第三篇)—prototype

(轉載自阮一峯的網絡日誌

發佈了32 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章