<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 技術儲備............

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

    閉包的兩個特點:

    1。作為一個函數變量的一個引用 - 當函數返回時,其處于激活狀態。
    2。一個閉包就是當一個函數返回時,一個沒有釋放資源的棧區。

    例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>

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

    上面的代碼為什么是一個閉包?
    因為sayHello2函數里有一個內嵌匿名函數
    sayAlert = function(){ alert(text); }
    在Javascript里。如果你創建了一個內嵌函數(如上例),也就是創建了一個閉包。

    在C或者其它的主流語言中,當一個函數返回后,所有的局部變量將不可訪問,因為它們所在的棧已經被消毀。但在Javascript里,如果你聲明了一個內嵌函數,局部變量將在函數返回后依然可訪問。比如上例中的變量sy,就是引用內嵌函數中的匿名函數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>
    這里也就與閉包的第二個特點相吻合。

    例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,并不是被拷貝,而是繼續引用外函數定義的局部變量——num中的值,直到外函數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都是同一個閉包的引用,setupSomeGlobals(),因為他們聲明都是通過同一個全局調用——setupSomeGlobals()。
    你可以通過“生成”,“增加”,“賦值”,“輸出值”這三個按扭來查看輸出結果。如果你點擊“生成”按鈕,將創建一個新閉包。也就會重寫gAlertNumber(), gIncreaseNumber(), gSetNumber(5)這三個函數。

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

    例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>
    運行結果:
    item 3 is undefined
    item 3 is undefined
    item 3 is undefined

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

    關于為什么會輸出三次都是 "item 3 is undefined"

    在上面的例子say667()例子中已經解釋過了。
    匿名函數function() {alert(item + ' ' + list[i])}中的list[i]并不是經過拷貝,而是對參數list的一個引用。直到函數buildList()返回為止,也就是說,返回最后一個引用。即遍歷完list(注:list的最大下標應該是2)后,經過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>

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

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 免费国产成人午夜私人影视| 成年女人18级毛片毛片免费观看| 亚洲人成无码www久久久| 亚洲色少妇熟女11p| 久久精品免费一区二区喷潮| 亚洲一区二区三区四区视频 | 亚洲深深色噜噜狠狠网站| 亚洲人成免费电影| 亚洲一欧洲中文字幕在线| 久久久久久久久免费看无码 | 老司机精品视频免费| 日本中文一区二区三区亚洲| 美女免费视频一区二区| 亚洲人成色77777在线观看大| h视频免费高清在线观看| 久久亚洲精品中文字幕无码| 114级毛片免费观看| 美女视频黄免费亚洲| 四虎国产精品免费视| 中文字幕免费在线观看动作大片| 日韩亚洲欧洲在线com91tv| 222www免费视频| 亚洲av无码av在线播放| 亚洲日韩VA无码中文字幕 | av无码久久久久不卡免费网站| 久久夜色精品国产噜噜亚洲a| 亚洲AV无码一区二区三区在线观看 | 人妻仑刮八A级毛片免费看| 亚洲乱色熟女一区二区三区丝袜| 97视频免费观看2区| 亚洲日本中文字幕天天更新| 亚洲精品无码激情AV| 免费在线视频你懂的| 99亚洲精品卡2卡三卡4卡2卡| 亚洲欧洲日产国码无码网站| 免费观看AV片在线播放| 大片免费观看92在线视频线视频| 亚洲综合日韩中文字幕v在线 | av在线亚洲欧洲日产一区二区| 国产精品成人观看视频免费 | 69视频免费在线观看|