**js中的繼承,是面向對象的知識,由於js沒有類的概念,因此繼承是經過對象實現的,談到繼承,就必須說到prototype,就不得不先說下new的過程。
一個小小的列子:**javascript
<script type="text/javascript"> var Person = function () { }; var p = new Person(); </script>
<1> var p={}; 也就是說,初始化一個對象p。java
<2> p.proto=Person.prototype;面試
<3> Person.call(p);也就是說構造p,也能夠稱之爲初始化p。this
關鍵在於第二步,咱們來證實一下:spa
alert(p.__proto__ === Person.prototype);
這段代碼會返回true。說明咱們步驟2的正確。prototype
那麼proto是什麼?咱們在這裏簡單地說下。每一個對象都會在其內部初始化一個屬性,就是proto,當咱們訪問一個對象的屬性 時,若是這個對象內部不存在這個屬性,那麼他就會去proto裏找這個屬性,這個proto又會有本身的proto,因而就這樣 一直找下去,也就是咱們平時所說的原型鏈的概念。code
按照標準,proto是不對外公開的,也就是說是個私有屬性,可是Firefox的引擎將他暴露了出來成爲了一個共有的屬性,咱們能夠對外訪問和設置。對象
<script type="text/javascript"> var Person = function () { }; Person.prototype.Say = function () { alert("Person say"); } var p = new Person(); p.Say(); </script>
這段代碼很簡單,相信每一個人都這樣寫過,那就讓咱們看下爲何p能夠訪問Person的Say。blog
首先var p=new Person();能夠得出p.proto=Person.prototype。那麼當咱們調用p.Say()時,首先p中沒有Say這個屬性, 因而,他就須要到他的proto中去找,也就是Person.prototype,而咱們在上面定義了 Person.prototype.Say=function(){}; 因而,就找到了這個方法。繼承
下面咱們再看一下有點饒人的列子。
function tiger(){ this.bark=function(){ alert("我會咬人"); }; }; //這裏先定義一個老虎方法 function cat(){ this.climb=function(){ alert("我會爬樹"); }; }; //定義一個貓方法 //怎麼經過繼承讓老虎也學會爬樹?下面開始繼承。 tiger.prototype=new cat(); var hnhu=new tiger(); hnhu.climb(); hnhu.valueof(); //是否是很神奇,老虎也會爬樹啦,嘿嘿
結合上面的概念,我分析一下具體的繼承過程,首先new一個tiger對象,有hnhu.proto=tiger.prototype,有由於tiger.prototype=new cat();
因此tiger.prototype.proto=cat.prototype。至此繼承已經付出水面,轉化一下獲得:
hnhu.proto=tiger.prototype
hnhu.proto.proto=cat.prototype
好,算清楚了以後咱們來看上面的結果,hnhu.climb()。因爲hnhu沒有climb這個屬性,因而去hnhu.proto,也就是 tiger.prototype中去找,因爲tiger.prototype中也沒有climb,那就去hnhu.proto.proto,也就是cat.prototype中去找,因而就找到了alert(「我會爬樹」);的方法。
尋找valueof()也都是一樣的道理。這條鏈就造成了原型鏈,繼承也就經過原型鏈得以實現。
以上代碼圖示:
原型和原型鏈就是這樣,跟做用域和做用域鏈相似,須要慢慢品味其中的精華。
掌握了在來實際用一下把,企鵝的一道繼承面試題,大概意思是一隻狗剛開始會嗚嗚的叫,而後發生某種變異,叫聲變爲變異。要求用原型繼承實現上述過程
function dog(){ this.fark=function(){ alert("嗚嗚"); }; }; function peter(){ this.money=function(){ alert("我是有錢狗"); }; }; peter.prototype=new dog(); peter.prototype.bark=function(){ alert("變異"); }; var tz=new peter(); tz.bark(); tz.fark();
你甚至能夠在Object.prototype上增長一些新屬性,添加上以後無論是否是變異狗都具備這項屬性,由於Object處於原型鏈的倒數第二層,上面的方法都會繼承它的屬性,可是這樣有必定的問題,全部的狗都具備這個原型鏈中的方法了。