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

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

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

    JAVA & XML & JAVASCRIPT & AJAX & CSS

    Web 2.0 技術(shù)儲(chǔ)備............

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      77 隨筆 :: 17 文章 :: 116 評(píng)論 :: 0 Trackbacks
    先把GC和Memory Leak探究暫時(shí)放下,牽涉的東西較多。需要逐一進(jìn)行解釋。
    比如這篇文章就是其中的一個(gè)影子——閉包(closure)。
    特別注明:我的翻譯是很爛的...:(,而且并沒有按原文那樣一路譯下來(lái),我只是抽取70%左右并加了一些自己的注釋。
    所以建議能讀懂英文的朋友,可以點(diǎn)擊最下面的鏈接去讀原文。

    閉包的兩個(gè)特點(diǎn):

    1。作為一個(gè)函數(shù)變量的一個(gè)引用 - 當(dāng)函數(shù)返回時(shí),其處于激活狀態(tài)。
    2。一個(gè)閉包就是當(dāng)一個(gè)函數(shù)返回時(shí),一個(gè)沒有釋放資源的棧區(qū)。

    例1。
    <script type="text/javascript">
    function sayHello2(name) {
    ?var text = 'Hello ' + name; // local variable
    ?var sayAlert = function() { alert(text); }
    ?return sayAlert;
    }
    var sy = sayHello2('never-online');
    sy();
    </script>

    作為一個(gè)Javascript程序員,應(yīng)該明白上面的代碼就是一個(gè)函數(shù)的引用。如果你還不明白或者不清楚的話,請(qǐng)先了解一些基本的知識(shí),我這里不再敘述。

    上面的代碼為什么是一個(gè)閉包?
    因?yàn)閟ayHello2函數(shù)里有一個(gè)內(nèi)嵌匿名函數(shù)
    sayAlert = function(){ alert(text); }
    在Javascript里。如果你創(chuàng)建了一個(gè)內(nèi)嵌函數(shù)(如上例),也就是創(chuàng)建了一個(gè)閉包。

    在C或者其它的主流語(yǔ)言中,當(dāng)一個(gè)函數(shù)返回后,所有的局部變量將不可訪問(wèn),因?yàn)樗鼈兯诘臈R呀?jīng)被消毀。但在Javascript里,如果你聲明了一個(gè)內(nèi)嵌函數(shù),局部變量將在函數(shù)返回后依然可訪問(wèn)。比如上例中的變量sy,就是引用內(nèi)嵌函數(shù)中的匿名函數(shù)function(){ alert(text); },可以把上例改成這樣:
    <script type="text/javascript">
    function sayHello2(name) {
    ?var text = 'Hello ' + name; // local variable
    ?var sayAlert = function() { alert(text); }
    ?return sayAlert;
    }
    var sy = sayHello2('never-online');
    alert(sy.toString());
    </script>
    這里也就與閉包的第二個(gè)特點(diǎn)相吻合。

    例2。
    <script type="text/javascript">
    function say667() {
    ?// Local variable that ends up within closure
    ?var num = 666;
    ?var sayAlert = function() { alert(num); }
    ?num++;
    ?return sayAlert;
    }

    var sy = say667();
    sy();
    alert(sy.toString());
    </script>

    上面的代碼中,匿名變量function() { alert(num); }中的num,并不是被拷貝,而是繼續(xù)引用外函數(shù)定義的局部變量——num中的值,直到外函數(shù)say667()返回。

    例3。
    <script type="text/javascript">
    function setupSomeGlobals() {
    ?// Local variable that ends up within closure
    ?var num = 666;
    ?// Store some references to functions as global variables
    ?gAlertNumber = function() { alert(num); }
    ?gIncreaseNumber = function() { num++; }
    ?gSetNumber = function(x) { num = x; }
    }

    </script>
    <button onclick="setupSomeGlobals()">生成 - setupSomeGlobals()</button>
    <button onclick="gAlertNumber()">輸出值 - gAlertNumber()</button>
    <button onclick="gIncreaseNumber()">增加 - gIncreaseNumber()</button>
    <button onclick="gSetNumber(5)">賦值5 - gSetNumber(5)</button>

    上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一個(gè)閉包的引用,setupSomeGlobals(),因?yàn)樗麄兟暶鞫际峭ㄟ^(guò)同一個(gè)全局調(diào)用——setupSomeGlobals()。
    你可以通過(guò)“生成”,“增加”,“賦值”,“輸出值”這三個(gè)按扭來(lái)查看輸出結(jié)果。如果你點(diǎn)擊“生成”按鈕,將創(chuàng)建一個(gè)新閉包。也就會(huì)重寫gAlertNumber(), gIncreaseNumber(), gSetNumber(5)這三個(gè)函數(shù)。

    如果理解以上代碼后,看下面的例子:

    例4。
    <script type="text/javascript">
    function buildList(list) {
    ?var result = [];
    ?for (var i = 0; i < list.length; i++) {
    ?var item = 'item' + list[i];
    ?result.push( function() {alert(item + ' ' + list[i])} );
    ?}
    ?return result;
    }

    function testList() {
    ?var fnlist = buildList([1,2,3]);
    ?// using j only to help prevent confusion - could use i
    ?for (var j = 0; j < fnlist.length; j++) {
    ?fnlist[j]();
    ?}
    }

    testList();
    </script>
    運(yùn)行結(jié)果:
    item 3 is undefined
    item 3 is undefined
    item 3 is undefined

    代碼result.push( function() {alert(item + ' ' + list[i])} ),
    使result數(shù)組添加了三個(gè)匿名函數(shù)的引用。這句代碼也可以寫成
    var p = function() {alert(item + ' ' + list[i])};
    result.push(p);

    關(guān)于為什么會(huì)輸出三次都是 "item 3 is undefined"

    在上面的例子say667()例子中已經(jīng)解釋過(guò)了。
    匿名函數(shù)function() {alert(item + ' ' + list[i])}中的list[i]并不是經(jīng)過(guò)拷貝,而是對(duì)參數(shù)list的一個(gè)引用。直到函數(shù)buildList()返回為止,也就是說(shuō),返回最后一個(gè)引用。即遍歷完list(注:list的最大下標(biāo)應(yīng)該是2)后,經(jīng)過(guò)i++也就變成了3,這也就是為什么是item 3,而list[3]本身是沒有初始化的,自然也就是undefined了。

    例5。
    <script type="text/javascript">
    function newClosure(someNum, someRef) {
    ?// Local variables that end up within closure
    ?var num = someNum;
    ?var anArray = [1,2,3];
    ?var ref = someRef;
    ?return function(x) {
    ?num += x;
    ?anArray.push(num);
    ?alert('num: ' + num +
    ?'\nanArray ' + anArray.toString() +
    ?'\nref.someVar ' + ref.someVar);
    ?}
    }
    var closure1 = newClosure(40, {someVar:' never-online'})
    var closure2 = newClosure(99, {someVar:' BlueDestiny'})
    closure1(4)
    closure2(3)
    </script>

    在這最后一個(gè)例子中,展示如何聲明兩個(gè)不同的閉包。
    posted on 2006-10-24 09:42 Web 2.0 技術(shù)資源 閱讀(217) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲一区二区三区在线观看精品中文 | 无码精品国产一区二区三区免费| 成人毛片免费在线观看| 亚洲av色香蕉一区二区三区蜜桃| 亚洲人成影院在线观看| 久久免费区一区二区三波多野| 中文字幕一精品亚洲无线一区| 免费精品无码AV片在线观看 | 激情综合亚洲色婷婷五月| 日韩人妻无码免费视频一区二区三区 | 国产高清免费在线| 国产一级淫片a免费播放口| 亚洲精品午夜国产va久久| 国产成人A在线观看视频免费| 免费精品久久久久久中文字幕| 久久综合亚洲色一区二区三区| 久久久久久久99精品免费| 亚洲熟妇AV日韩熟妇在线| 色噜噜亚洲精品中文字幕| 国产免费av片在线看| 成在线人免费无码高潮喷水| 亚洲综合精品网站| 91精品免费在线观看| 亚洲狠狠色丁香婷婷综合| 四虎国产精品免费视| 深夜A级毛片视频免费| 亚洲自偷自拍另类图片二区| 亚洲成片观看四虎永久| 国产猛男猛女超爽免费视频| 99亚洲乱人伦aⅴ精品| 中文字幕亚洲日韩无线码| 午夜精品一区二区三区免费视频| 亚洲国产成人精品无码区二本| 亚洲国产精品久久久久婷婷老年| 精品无码人妻一区二区免费蜜桃| 在线亚洲v日韩v| 亚洲娇小性xxxx色| 久久亚洲国产成人精品性色| 亚洲男女内射在线播放| 无码高潮少妇毛多水多水免费| 久久免费精彩视频|