javascript繼承一直很差理解,每次遇到了看了彷佛懂了,可是沒有完全研究過並且遇到一次忘記一次,此次想完全的解決掉,用最簡單直白的闡述。引入了前輩的一些見解,進行了收集加工整理。
用百度腦圖作了整理javascript
javascript出現是爲了加強用戶和瀏覽器之間的交互。好比,若是網頁上有一欄"用戶名"要求填寫,瀏覽器就沒法判斷訪問者是否真的填寫了,只有讓服務器端判斷。若是沒有填寫,服務器端就返回錯誤,要求用戶從新填寫,這太浪費時間和服務器資源了。
當時javascript的做者Brendan Eich受到當時面向對象編程的影響,主要是Java的影響,Javascript裏面全部的數據類型都是對象(object)。這時候,他要考慮一個問題,javascript到底需不須要繼承?html
javascript中是沒有「類」這個概念的,new 後面不是面向對象編程中的「類」,而是構造函數。如例:java
function DOG(name){ this.name = name; } //對這個構造函數使用new,就會生成一個狗對象的實例。var dogA = new DOG('大毛'); alert(dogA.name); // 大毛
用構造函數生成實例對象,有一個缺點,那就是沒法共享屬性和方法。編程
function DOG(name){ this.name = name; this.species = '犬科'; } //生成兩個實例對象:var dogA = new DOG('大毛'); var dogB = new DOG('二毛'); dogA.species = '貓科'; alert(dogB.species); // 顯示"犬科",不受dogA的影響
每個實例對象,都有本身的屬性和方法的副本。這不只沒法作到數據共享,也是極大的資源浪費。數組
考慮到這一點,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); // 貓科
因爲全部的實例對象共享同一個prototype對象,那麼從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象同樣。ui
關於第一章節爲阮一峯《Javascript繼承機制的設計思想》中觀點。
構造函數 就是一個普通的函數,一般當函數名 爲 大寫開頭的,咱們認爲是構造函數,不然 就是普通的方法。
// 構造函數function A() { this.name = 'A Class instance'; } // 普通方法function m1() { }
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
四,參考的資料和筆記: