javascript基礎之我見(1)—-深度理解原型鏈

來源:互聯網
上載者:User

寫在開始之前:

  早就想要好好總結下javascript的基礎知識了,所以從這篇文章起,我會開始總結各種js的文法知識,作為一名以js開發為生計的前端工程師,深深的著迷於js的語言魅力,而js最吸引人最強大的地方,便在於他獨特的文法,能深刻的理解js的文法,是作為一個前端工程師的基本素質,在這裡,筆者在總結的同時,也希望前端朋友們給予自己的補充和見解。那麼就讓我們從js最最獨特的文法,閉包,原型,詞法範圍開始,接下來,筆者也會討論this,正則,瀏覽器的能力檢測,事件代理等細節問題,以及html5,css3等前沿領域,今天我先試著總結下原型鏈相關的知識。筆者的經驗和知識也許會有很多不足之處,歡迎大家的更正與建議。

 

1.首先要知道的:

  什麼是原型鏈呢?

  我們首先來說說繼承,繼承是物件導向語言的重要機制,通俗地講就是子類可以擁有父類的方法和屬性,js的原型鏈實際上也是一種繼承,在ECMAScript標準中,只支援實現繼承,而其實現實現繼承就是主要依靠於原型鏈實現的。

  那麼,我們再來說說原型,原型其實就是上述所說的繼承中的父類。

  這樣,原型鏈 顯而易見的 可以理解為,利用原型串起一個繼承鏈,讓一個參考型別繼承另一個參考型別的屬性和方法,再以此類推下去。

  建構函式,原型,與執行個體的關係:

  這三者的關係用一句話概括為,每個建構函式都有一個原型,當new 一個建構函式的時候就會產生一個原型鏈上攜帶該建構函式的原型的執行個體。

2.原型鏈的產生過程:  

  上面基本瞭解了原型鏈的相關知識,那麼原型鏈的產生過程是什麼呢?

1 function parent(){
  this.parent = "world";2 }3 parent.prototype = {4 a : function(){5   },6 b : "hello"7 }8 var child = new parent()

   而child就是parent的一個執行個體,在執行建構函式的時候,js引擎建立一個空白對象,把__proto__指向parent的prototype,然後把這個對象作為this調用parent進行初始化,這樣一個簡單的原型鏈就形成了 即 child --> parent.prototye -->Object.prototype。

    prototype,constructor,__proto__ : 

  上面多次提到這幾個屬性,在原型鏈的概念中,如果能理解這幾個屬性的關係,那麼離勝利就不遠了。下面我們逐一的談談這幾個屬性:

  1.prototype

  prototype是建構函式的屬性,指的就是建構函式的原型,在產生執行個體的時候,js會根據建構函式的prototype屬性將該屬性下的對象產生為父類,

     注意,只有建構函式這個屬性才有這種效果哦~如果一個建構函式沒有指定該屬性,那麼該屬性下的__proto__會預設的指向原生Object的原型對象,該屬性會變成一個對象,其中constructor屬性指向本身。

  2.constructor

     constructor,如果通俗的理解,可以理解成原型對象的建構函式,當把一個對象(對象字面量)賦給一個建構函式的原型,constructor會被複寫,如果沒有進行prototype的操作的話,constructor是函式宣告時指定的,指定為本身:

  例如:

  function A() {}
  則 A.prototype.constructor === A;

但是這個屬性往往是不準確的:

1 function A() {}2 function B() {}3 B.prototype = new A();4 var b = new B();5 b.constructor; // A

  上面的代碼,按照constructor的含義,b的constructor應該指向B,但是確指向了A,原因如下

    A沒有進行prototype操作,所以其constructor指向本身;
  B.prototype = new A();之後B.prototype被複寫為A的執行個體,
  則B.prototype.constructor === A;
  而b是B的執行個體則b.constructor === A;   所以constructor這個屬性是不準確的,不推薦大家關注與使用。  

  如果想要實現繼承,一般要進行constructor修複,即:
  B.prototype = new A();
  B.prototype.constructor = B;

  3.__proto__  可以這麼說,js的原型鏈就是通過這個屬性串聯起來的,__proto__屬性指向他的父類,在調用一個對象的屬性或者方法的時候就是通過__proto__這一屬性指向的對象一層一層的向上尋找的。上面的一句:在產生執行個體的時候,js會根據建構函式的prototype屬性將該屬性下的對象產生為父類,在這裡可以改為,在產生執行個體的時候,js會根據建構函式的prototype屬性將該屬性下的對象引用到執行個體的__proto__屬性下。     

 1 function parent(){ 2     this.a = "world"; 3     this.b = "world"; 4 } 5 parent.prototype = { 6    a : "aaa", 7    b : "bbb", 8    c : "!"  9 }10 function temp(){11    this.a = "hello";12 }13 temp.prototype = new parent();14 var child = new temp();15 console.log(child.a +" " + child.b+child.c);//hello world!

  上面的代碼運行結果就為 : “hello world!”產生的原型鏈即是

  child(temp的執行個體) > __proto__ > temp.prototype(parent的執行個體) > __proto__  >parent.prototype > __proto__ > Object.prototype >__proto__ > null

3.原型鏈的調用

  如上所示,原型鏈由__proto__屬性串聯而成,經過上面的分析,調用的理解就變得很簡單了,比如上例的原型鏈中,當調用child.c屬性時,那麼程式會按如下方式運行:

  在child本層尋找c,查詢未果,會通過__proto__屬性向上尋找temp.prototype,尋找未果,繼續沿著__proto__向上尋找parent.prototype,oyeah~終於找到了~所以child.c在這裡就會是parent.prototype.c了~

  怎麼樣,簡單吧^ ^

 

最後的最後,呈上一個常用函數給大家:

  

 1 function A() { 2      // do something here 3 } 4 A.prototype = { 5      a : 'aaa', 6      b : function() { 7      } 8 }; 9  function B() {10 }11 extend(B, A);12 function extend(child, parent) {13      function temp() {14             this.constructor = child;15     }16      temp.prototype = parent.prototype;17      child.prototype = new temp();18 }

  extend函數 兩個參數都為建構函式,目的是讓一個建構函式(子類)繼承另一個建構函式(父類)的原型,並且不調用父類的建構函式(有時候建構函式會需要一些參數或者做一些事情破壞了原型鏈),這個方法可以用來產生想要的原型鏈哦。

 

  好了,今天就總結這麼多,以後繼續總結其他的js文法知識

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.