javascript 原型鏈維護(hù)和繼承詳解

    時間:2024-10-25 19:00:49 JavaScript 我要投稿
    • 相關(guān)推薦

    關(guān)于javascript 原型鏈維護(hù)和繼承詳解

      一.兩個原型

      很多人都知道javascript是原型繼承,每個構(gòu)造函數(shù)都有一個prototype成員,通過它就可以把javascript的繼承演義的美輪美奐了.

      其實(shí)啊,光靠這一個屬性是無法完成javascript的繼承.

      我們在代碼中使用的prototype完成繼承在這里就不多說了.大家可以查一下資料.

      另外一個看不見的prototype成員.

      每一個實(shí)例都有有一條指向原型的prototype屬性,這個屬性是無法被訪問到的,當(dāng)然也就無法被修改了,因?yàn)檫@是維護(hù)javascript繼承的基礎(chǔ).

      復(fù)制代碼 代碼如下:

      //構(gòu)造器聲明

      function Guoyansi(){ }

      function GuoyansiEx(){}

      //原型繼承

      GuoyansiEx.prototype=new Guoyansi();

      //創(chuàng)建對象

      var g1=new GuoyansiEx();

      var g2=new GuoyansiEx();

      上面的代碼中的對象可以用下面的圖來說明

      二.原型的維護(hù)

      一個構(gòu)造器產(chǎn)生的實(shí)例,其constructor屬性總是指向該構(gòu)造器.我們暫且認(rèn)為該話是對的.

      復(fù)制代碼 代碼如下:

      function Guoyansi(){ }

      var obj1=new Guoyansi();

      console.log(obj1.constructor===Guoyansi);//true

      其實(shí)構(gòu)造器本身是沒有constructor這個屬性的,那么這個屬性是來自哪呢?

      答案是:來自原型.

      因此得出下面的結(jié)論

      復(fù)制代碼 代碼如下:obj1.constructor===Guoyansi.prototype.constructor===Guoyansi

      既然我們可以通過constructor來尋找構(gòu)造器.因此我們就可以進(jìn)一步完善上面的圖了.

      復(fù)制代碼 代碼如下:

      function GuoyansiEx(){}

      GuoyansiEx.prototype=new Guoyansi();

      console.log(GuoyansiEx.constructor===GuoyansiEx)//false

      根據(jù)上圖,上面的結(jié)果應(yīng)該是true,但為什么是false呢?

      現(xiàn)在做個分析.

      GuoyansiEx的原型被Guoyansi的實(shí)例重寫了,那么GuoyansiEx的原型中的constructor自然也是來自Guoyansi的實(shí)例.

      而Guoyansi實(shí)例中的constructor又是來自Guoyansi.prototype.而Guoyansi.prototype沒有被重寫,

      所以Guoyansi.prototype的constructor指向Guoyansi(構(gòu)造函數(shù));

      根據(jù)以上分析得出下面的結(jié)論

      復(fù)制代碼 代碼如下:GuoyansiEx.constructor===Guoyansi.constructor===Guoyansi;

      如果在開發(fā)過程中對于Constructor的指向要求非常精確的話,可以做如下處理.

      復(fù)制代碼 代碼如下:

      /**方法一:**/

      function Guoyansi(){}

      function GuoyansiEx(){}

      GuoyansiEx.prototype=new Guoyansi();

      GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

      復(fù)制代碼 代碼如下:

      /**

      方法二

      **/

      function Guoyansi(){}

      function GuoyansiEx(){

      this.constructor=arguments.callee;

      }

      GuoyansiEx.prototype=new Guoyansi();

      復(fù)制代碼 代碼如下:

      /**

      方法三

      **/

      function Guoyansi(){}

      function GuoyansiEx(){

      this.constructor=GuoyansiEx;

      }

      GuoyansiEx.prototype=new Guoyansi();

      三.看不見的原型有什么用呢?

      看得見的原型鏈我們可以對他操作來完成我們的繼承,那么這個看不見的原型鏈我們既看不見,又無法操作.要它有何用.

      面向?qū)ο笾欣^承有一個特性:相似性.子類與父類具有相似性.因此在子類中你是無法用刪除從父類繼承而來的成員.也就是說子類必須具有父類的特性.

      為了維護(hù)這個特性,javascript在對象的內(nèi)部產(chǎn)生了一條我們看不見的原型屬性,并且不允許用戶訪問.這樣,用戶可以處于任何目的來修改constructor,

      而不會破壞子類擁有父類的特性.

      簡而言之:內(nèi)部原型是javascript的原型繼承機(jī)制所需要的,而外部原型是用戶實(shí)現(xiàn)繼承所需要的.

      四.火狐引擎SpiderMonkey中的__proto__

      還是這段代碼.

      復(fù)制代碼 代碼如下:

      function Guoyansi(){}

      Guoyansi.prototype.age=24;

      function GuoyansiEx(){}

      var obj1=new Guoyansi();

      GuoyansiEx.prototype=obj1;

      GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

      var obj2=new GuoyansiEx();

      我現(xiàn)在想要從obj開始向上訪問父類Guoyansi的prototype的屬性的age.

      思路是這樣的.

      第一步:obj2====>obj2.constructor.prototype

      第二部:obj2.constructor.prototype===>GuoyansiEx.prototype;

      第三部:GuoyansiEx.prototype===>obj1;

      第四部:obj1.constructor====>Guoyansi

      第五部:Guoyansi.prototype.age

      寫成這這樣:console.log(obj2.constructor.prototype.constructor.prototype.age)//24;

      最終的結(jié)果是24.

      最終的結(jié)果是24.可以正常執(zhí)行,但是在好多書上說constructor修改后,級無法在找到父類中的原型了.不知道是怎么回事.

      在火狐中提夠了一種更加簡潔的屬性._proto_

      SpiderMonkey中默認(rèn)在任何創(chuàng)建的對象上添加了一個名為_proto_的屬性,該屬性指向構(gòu)造器所用的原型.

      其實(shí)就是我們上面提到的不可見的原型鏈,只不過是在這個地方變相的公開而已.

      可以這樣訪問到age

      console.log(obj2.__proto__.__proto__.age);//24

      這樣的確是成功的訪問到了父類的原型屬性,但是這個屬性只適用于火狐,在其他瀏覽器中是會出錯的.

      在E5中對Object做出了擴(kuò)展Object.getPrototypeOf(),可以訪問到所有父類的原型了.

      復(fù)制代碼 代碼如下:

      function Guoyansi(){}

      Guoyansi.prototype.age=24;

      function GuoyansiEx(){}

      var obj1=new Guoyansi();

      GuoyansiEx.prototype=obj1;

      GuoyansiEx.prototype.constructor=GuoyansiEx;//重置constructor指向.

      var obj2=new GuoyansiEx();

      var proto=Object.getPrototypeOf(obj2);

      while(proto){

      console.log(proto.constructor);

      proto=Object.getPrototypeOf(proto);

      }

      console.log("object的原型"+proto);

      結(jié)果是:GuoyansiEx

      Guoyansi

      Object

      object的原型null

      個人覺得這些應(yīng)該算是javascript面向?qū)ο蟮木柚涣?小伙伴們自己參考下,根據(jù)需求使用到自己的項(xiàng)目中去吧

    【javascript 原型鏈維護(hù)和繼承詳解】相關(guān)文章:

    理解JavaScript原型鏈教程09-02

    Javascript中arguments對象的詳解和使用方法08-20

    JavaScript中push(),join() 函數(shù)實(shí)例詳解09-05

    詳解SEO外鏈本質(zhì)10-24

    詳解JavaScript中的splice()使用方法08-20

    JavaScript類定義原型方法的兩種實(shí)現(xiàn)的區(qū)別07-11

    Javascript函數(shù)的定義和用法分析08-15

    網(wǎng)站外鏈與網(wǎng)站優(yōu)化的之間關(guān)系詳解10-24

    網(wǎng)站內(nèi)鏈和外鏈的定義及區(qū)別09-28

    如何提高網(wǎng)站內(nèi)鏈和外鏈的收錄?08-09

    91久久大香伊蕉在人线_国产综合色产在线观看_欧美亚洲人成网站在线观看_亚洲第一无码精品立川理惠

      亚洲囯产一区二区三区 | 亚洲人成网站色在线 | 亚洲国产精品久久无套 | 一区二区中文字幕 | 亚洲乱码中文字字幕 | 亚洲国产欧美日韩另类精品一区二区在线 |