<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 310, comments - 6939, trackbacks - 0, articles - 3
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    JavaScript Prototype 詳解(轉(zhuǎn)載)

    Posted on 2009-04-26 16:54 詩特林 閱讀(5298) 評論(1)  編輯  收藏 所屬分類: JavaScript

    本文里講述的是關(guān)于JavaScript的prototype問題,至于具體的JavaScript面向?qū)ο蟮木幊探坛蹋埜魑豢纯偷狡渌W(wǎng)站搜索一下,或者到這里看看。

    首先開始一個例子,如下:


    1 function A() {
    2     this.t1 = "ffffff";
    3     this.t2 = function (msg) {
    4         alert(msg);
    5     };
    6 };
    7
    8 A.prototype.p1 = "xxxx";
    9
    10 A.prototype.f1 = function () {
    11      do something.
    12 };
    其實p1,f1是對function的prototype對象的操作,大家要明白,function
    也是一個對象,對象也有屬性,而prototype就是function的屬性,該屬性
    也是一個對象,不同之處是,function在做為類定義的時候,創(chuàng)建類實例的
    過程(new的過程)要參照它的prototype對象,把prototype對象的所有
    屬性(也就是Java里的成員,包括成員變量和成員函數(shù))都復(fù)制到新的對象
    中去,所以可以看出prototype就是模板,而這個模板是在new一個對象之
    前就已經(jīng)存在了。

    上面的JavaScript就好像在定義一個Java類,書寫類的時候,除了用不同的聲明
    (Class和Function)區(qū)別,基本沒有其他的區(qū)別,但在運行時有很大的區(qū)別。
    首先Java要求類必須被編譯成字節(jié)碼才能被載入虛擬機,而JavaScript是在運行
    代碼的同時,執(zhí)行了類似Java的編譯載入的過程。并且Java的類在載入虛擬機
    后一般就不能再改變類的定義了,比如把一個方法的行為改變或指向另一個方
    法的引用等。而JavaScript在運行期還可以通過prototype來改變類及所有該類生成
    的對象的行為。例如上面的例子中,在解析完function A的函數(shù)體后,整個類也
    就生成了,這時候如果new的話就能得到類的實例,緊接著的代碼又向類動態(tài)
    添加了新的行為。

    而在function A的函數(shù)體內(nèi)定義的this成員,可以理解為‘后’綁定成員。
    可以這么理解,在new A()的時候JavaScript建立了一個臨時對象,
    把A.prototype的所有成員復(fù)制到臨時對象中,然后再把函數(shù)A中
    定義的this成員也綁定到臨時對象中,然后把臨時對象返回給用戶。
    下面是模擬JavaScript的new關(guān)鍵字的處理偽過程:

    //建立臨時對象
    var tobj = {};
    //復(fù)制prototype
    for (var key in A.prototype)
    tobj[key] = A.prototype[key];
    //綁定函數(shù)體內(nèi)的this成員(這個過程是JavaScript的內(nèi)部處理,沒有辦法模擬)
    return tobj to user;

    之所以存在function內(nèi)部定義的this成員,以及prototype的成員是
    有原因的。由于JavaScript的類在構(gòu)造時是可以傳遞構(gòu)造參數(shù)的,
    所以,this成員的行為可能由于參數(shù)的不同而不同。這也就是需要后
    綁定的原因了。在看下一個例子:

    1 function AA(val1,val2) {
    2     this.test1 = function() {
    3         alert(val1);
    4     };
    5
    6     this.test2 = val2 ? function () { return this.test1;} : function () { return 456; };
    7
    8     this.test3 = val1 ? val1 : function () {alert("no val1");};
    9 }
    這個例子很好的說明了后綁定的實際使用價值,所以后綁定對于成員
    函數(shù)來說是非常有用的,對于成員變量來說其實沒什么實際用處。
    唯一不同的是,this成員在每次new對象時都要被JavaScript引擎解析,
    原因很簡單,根據(jù)不同的構(gòu)造參數(shù),使它們在運行期的行為可能有很大
    的不同。而prototype的成員就不會每次都解析,第一次定義prototype
    成員時才解析,以后可以直接引用prototype成員,并且更改了prototype
    成員,所有已經(jīng)建立的實例對象的相應(yīng)成員都會被更改。

    在運行期可以通過'對象名.成員名'來更改成員,這種方式可以更改this成員
    和prototype成員的默認定義,但是更改只限于自身對象,因為JavaScript
    和Java一樣,也是傳值,對象的引用也是一個地址值,所以new一個對象后,
    prototype的成員也被復(fù)制到那個對象上了,再更改那個對象的成員,只會
    影響那個對象自身,其他從同一個類new出來的對象都不會有任何變化。

    不能通過運行期設(shè)置'類.prototype.成員名'來覆蓋this同名成員,這樣做沒有
    任何效果。

    通過復(fù)制一個對象的所有屬性到一個新對象,是不能通過修改prototype成員
    來修改新對象的成員行為,因為新對象不是通過原來對象的類new出來的。
    通常的復(fù)制方法如下:

    1 var tobj = {};
    2 for (var key in otherObj)
    3     tobj[key] = otherObj[key];
    看似tobj和otherObj的行為是一致的,他們不是一個類new出來的。
    一個很好的辦法可以測試,比如otherObj是A類new出來的,
    可以通過使用 (tobj instanceof A) 來測試,結(jié)果顯然是false。

    最新的測試表明,這種復(fù)制方法可以復(fù)制所有自定義方法,
    但是系統(tǒng)提供的默認方法是不能被復(fù)制的,即使你顯式的覆蓋了
    系統(tǒng)默認提供的方法,如toString方法等。

    最后再談?wù)刾rototype的constructor成員,該成員是對一個類的構(gòu)造
    函數(shù)的引用,在類定義的初期,如果一個類沒有從其他別的類那
    里繼承,該類的prototype.constructor屬性保存的是該類自身的引用,
    如果該類從別的類繼承,那么它的constructor屬性就保存了父類的
    constructor引用,一般constructor沒有什么用處,但可以通過它來取
    得他的類的信息,就像Java里的對象都有g(shù)etClass()方法,constructor
    就是干這個用的。有它的好處是,再運行期可以改變所有同類對象
    的成員行為,如:

    1 someObj.constructor.prototype.somePrototype = function () {
    2 other process .
    3 }
    因此好的習(xí)慣是在繼承之后把prototype的constructor成員設(shè)置一下,
    否則會把父類的prototype成員改掉,那樣程序的行為就不可預(yù)知了。
    如:

    1 function classA() {
    2
    3 }
    4
    5 classB.prototype = new classA();
    6 classB.prototype.constructor = classB;
    7
    我要說的關(guān)于JavaScript的prototype屬性就這么多,大家多提意見多交流。


    評論

    # re: JavaScript Prototype 詳解(轉(zhuǎn)載)  回復(fù)  更多評論   

    2011-11-05 18:24 by 范秋海
    有錯誤。
    例如:
    var A = function(a){this.a = a};
    A.prototype.b = 0;
    var a1 = new A(1); a1.b = 2;
    var a2 = new A(2);
    alert(a1.a) 輸出1,
    alert(a1.b) 輸出2
    alert(a2.a) 輸出2
    alert(a2.b) 輸出0

    但是如果是這種情況:
    var A = function(a){this.a = a};
    A.prototype.b = {};
    var a1 = new A(1); a1.b.b = 2;
    var a2 = new A(2);
    alert(a1.a) 輸出1,
    alert(a1.b.b) 輸出2
    alert(a2.a) 輸出2
    注意:
    alert(a2.b.b) 輸出2
    主站蜘蛛池模板: 中文字幕在线视频免费观看| 精品在线视频免费| 东方aⅴ免费观看久久av| 国产精品亚洲αv天堂无码| 日本亚洲高清乱码中文在线观看| 巨胸喷奶水视频www网免费| 亚洲精品无码久久久久YW| 毛片网站免费在线观看| 亚洲中文字幕无码av| 午夜小视频免费观看| 国产精品久久久久久亚洲影视| 麻豆国产入口在线观看免费| 亚洲国产精品日韩av不卡在线| 精品免费久久久久久成人影院| 亚洲精品乱码久久久久久V | 一级特黄色毛片免费看| 一本色道久久综合亚洲精品高清| fc2免费人成为视频| 亚洲AV无码乱码在线观看富二代| 国产午夜无码精品免费看| 精品亚洲成a人片在线观看| 日本最新免费网站| 亚洲AV无码一区二区三区牲色 | 91麻豆精品国产自产在线观看亚洲| 中文字幕av无码不卡免费 | xxx毛茸茸的亚洲| 韩国18福利视频免费观看| 美女被暴羞羞免费视频| 日日噜噜噜噜夜夜爽亚洲精品| 久久久久久一品道精品免费看 | 高清在线亚洲精品国产二区| 又大又硬又粗又黄的视频免费看| 国产亚洲高清不卡在线观看| 久久久精品2019免费观看| 亚洲欧洲日韩国产一区二区三区| 免费国产成人午夜私人影视| 中文字幕在线免费视频| 亚洲视频免费播放| 又粗又大又硬又爽的免费视频 | 亚洲免费福利在线视频| 日韩精品视频在线观看免费|