<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ù)儲備............

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

    閉包的兩個特點:

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

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

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

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

    例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都是同一個閉包的引用,setupSomeGlobals(),因為他們聲明都是通過同一個全局調(diào)用——setupSomeGlobals()。
    你可以通過“生成”,“增加”,“賦值”,“輸出值”這三個按扭來查看輸出結(jié)果。如果你點擊“生成”按鈕,將創(chuàng)建一個新閉包。也就會重寫gAlertNumber(), gIncreaseNumber(), gSetNumber(5)這三個函數(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>
    運行結(jié)果:
    item 3 is undefined
    item 3 is undefined
    item 3 is undefined

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

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

    在上面的例子say667()例子中已經(jīng)解釋過了。
    匿名函數(shù)function() {alert(item + ' ' + list[i])}中的list[i]并不是經(jīng)過拷貝,而是對參數(shù)list的一個引用。直到函數(shù)buildList()返回為止,也就是說,返回最后一個引用。即遍歷完list(注:list的最大下標(biāo)應(yīng)該是2)后,經(jīng)過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 技術(shù)資源 閱讀(214) 評論(0)  編輯  收藏

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


    網(wǎng)站導(dǎo)航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 亚洲午夜一区二区电影院| 国产成人综合亚洲AV第一页| 亚洲av日韩av无码黑人| 国产精品高清免费网站| 亚洲啪啪AV无码片| 亚洲综合精品香蕉久久网97| a级毛片免费观看在线| 亚洲人成色7777在线观看不卡| 亚洲国产精品第一区二区| 国产精品亚洲专区无码牛牛| 成人午夜性A级毛片免费| 亚洲欧洲AV无码专区| 国产成人无码a区在线观看视频免费| 亚洲综合av一区二区三区不卡| 好先生在线观看免费播放| 亚洲精品无码不卡在线播放HE| 拍拍拍无挡免费视频网站| 亚洲AV永久青草无码精品| 84pao强力永久免费高清| 亚洲网站视频在线观看| 美女网站免费福利视频| 最新亚洲春色Av无码专区| 国产一区视频在线免费观看 | 777成影片免费观看| 亚洲专区一路线二| 日本特黄特黄刺激大片免费| 亚洲综合在线成人一区| 在线视频免费观看高清| 国产精品亚洲色图| 免费无码不卡视频在线观看| 边摸边吃奶边做爽免费视频99| 亚洲一区日韩高清中文字幕亚洲 | 亚洲人成网亚洲欧洲无码| vvvv99日韩精品亚洲| 亚洲妇女无套内射精| 亚洲人成网站观看在线播放| 无码免费一区二区三区免费播放 | 免费黄色一级毛片| 一级人做人爰a全过程免费视频| 国产一区视频在线免费观看 | 亚洲一卡2卡3卡4卡乱码 在线 |