javascript 繼承(轉)

 

     javascript繼承一直很差理解,每次遇到了看了彷佛懂了,可是沒有完全研究過並且遇到一次忘記一次,此次想完全的解決掉,用最簡單直白的闡述。引入了前輩的一些見解,進行了收集加工整理。
用百度腦圖作了整理javascript

一,javascript中繼承的由來

1-1.javascript的出現

     javascript出現是爲了加強用戶和瀏覽器之間的交互。好比,若是網頁上有一欄"用戶名"要求填寫,瀏覽器就沒法判斷訪問者是否真的填寫了,只有讓服務器端判斷。若是沒有填寫,服務器端就返回錯誤,要求用戶從新填寫,這太浪費時間和服務器資源了。
當時javascript的做者Brendan Eich受到當時面向對象編程的影響,主要是Java的影響,Javascript裏面全部的數據類型都是對象(object)。這時候,他要考慮一個問題,javascript到底需不須要繼承?html

1-2.Brendan Eich的選擇

     javascript中是沒有「類」這個概念的,new 後面不是面向對象編程中的「類」,而是構造函數。如例:java

function DOG(name){
    this.name = name;
}
//對這個構造函數使用new,就會生成一個狗對象的實例。var dogA = new DOG('大毛');
alert(dogA.name); // 大毛

1-3.new運算符的缺點

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

function DOG(name){
    this.name = name;
  this.species = '犬科';
}
//生成兩個實例對象:var dogA = new DOG('大毛');
var dogB = new DOG('二毛');

dogA.species = '貓科';
alert(dogB.species); // 顯示"犬科",不受dogA的影響

     每個實例對象,都有本身的屬性和方法的副本。這不只沒法作到數據共享,也是極大的資源浪費。數組

1-4.prototype屬性的引入

     考慮到這一點,Brendan Eich決定爲構造函數設置一個prototype屬性。瀏覽器

     這個屬性包含一個對象(如下簡稱"prototype對象"),全部實例對象須要共享的屬性和方法,都放在這個對象裏面;那些不須要共享的屬性和方法,就放在構造函數裏面。服務器

     實例對象一旦建立,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法,分紅兩種,一種是本地的,另外一種是引用的。ide

如例:函數

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

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

alert(dogA.species); // 犬科
alert(dogB.species); // 犬科//只要修改了prototype對象,就會同時影響到兩個實例對象。
DOG.prototype.species = '貓科';
alert(dogA.species); // 貓科
alert(dogB.species); // 貓科

1-5 總結

     因爲全部的實例對象共享同一個prototype對象,那麼從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象同樣。ui

關於第一章節爲阮一峯《Javascript繼承機制的設計思想》中觀點。

二,構造函數

     構造函數 就是一個普通的函數,一般當函數名 爲 大寫開頭的,咱們認爲是構造函數,不然 就是普通的方法。

// 構造函數function A() {
    this.name = 'A Class instance';
}
// 普通方法function m1() {
}

三.Null是原型鏈的最後一環

JavaScript只有一種結構:對象。每一個對象都有一個內部連接指向另外一個對象,這個對象稱爲原型 (prototype)。那個原型對象也有本身的原型,如此直到某個對象以null做爲其原型。null,根據定義,沒有原型,做爲這種原型鏈的最後一環而存在。

     嘗試用語言去解釋

// 假設有個對象o,其原型鏈以下所示:// var o = {a: 1, b: 2} ---> {b: 3, c: 4} ---> null// 'a'和'b'是o的自有屬性。

// 本例中,someObject.[[Prototype]]指定someObject的原型。// 這徹底是一種標記符號(基於ECMAScript標準中所使用的),不可用於腳本中。

console.log(o.a);   // 1// o有一個自有屬性'a'嗎?是的,其值爲1

console.log(o.b);   // 2// o有自有屬性'b'嗎?是的,其值爲2// o的原型也有一個屬性'b',可是這裏不會被訪問。這被稱爲「屬性隱藏」(property shadowing)

console.log(o.c);   // 4// o有自有屬性'c'嗎?沒有,檢查它的原型// o.[[Prototype]]有自有屬性'c'嗎?是的,其值爲4。

console.log(o.d);   // undefined// o有自有屬性'd'嗎?沒有,檢查其原型// o.[[Prototype]]有自有屬性'd'嗎?沒有,檢查其原型// o.[[Prototype]].[[Prototype]]爲null,中止搜索,沒有找到屬性,返回undefined。

咱們用代碼去解釋

var o = {a: 1};

// 新建立的對象o有Object.prototype做爲其[[Prototype]]// o沒有名爲'hasOwnProperty'的自有屬性// hasOwnProperty是Object.prototype的自有屬性。所以o從Object.prototype繼承了hasOwnProperty// Object.prototype以null爲其prototype。// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// 數組繼承自Array.prototype(它具備indexOf, forEach等方法)。// 該原型鏈以下所示:// a ---> Array.prototype ---> Object.prototype ---> null

function f() {
    return 2;
}

// 函數繼承自Function.prototype(它具備call,bind等方法):// f ---> Function.prototype ---> Object.prototype ---> null

四,參考的資料和筆記:

相關文章
相關標籤/搜索