首頁 > web前端 > js教程 > 詳談JavaScript 匿名函數及閉包_javascript技巧

詳談JavaScript 匿名函數及閉包_javascript技巧

WBOY
發布: 2016-05-16 16:31:26
原創
1333 人瀏覽過

1、匿名函數
函數是JavaScript中最靈活的一種對象,這裡只是講解其匿名函數的用途。匿名函數:就是沒有函數名的函數。

1.1 函數的定義,先簡單介紹一下函數的定義,大致可分為三種方式

第一種:這也是最常規的一種

複製程式碼 程式碼如下:

function double(x){
    return 2 * x;  
}

第二種:這種方法使用了Function建構函數,把參數列表和函數體都當作字串,很不方便,不建議使用。

複製程式碼 程式碼如下:

var double = new Function('x', 'return 2 * x;');

第三種:

var double = function(x) { return 2* x; }
注意「=」右邊的函數就是一個匿名函數,創造完畢函數後,又將該函數賦給了變數square。

1.2 匿名函數的建立

第一種方式:就是上面所講的定義square函數,這也是最常用的方式之一。

第二種方式:

複製程式碼 程式碼如下:

(function(x, y){
    alert(x y); 
})(2, 3);

這裡建立了一個匿名函數(在第一個括號內),第二個括號用來呼叫這個匿名函數,並傳入參數。

2、閉包
閉包的英文單字是closure,這是JavaScript中非常重要的一部分知識,因為使用閉包可以大幅減少我們的程式碼量,使我們的程式碼看起來更加清晰等等,總之功能十分強大。

閉包的意思:閉包說白了就是函數的嵌套,內層的函數可以使用外層函數的所有變量,即使外層函數已經執行完畢(這點涉及JavaScript作用域鏈)。

範例一

複製程式碼 程式碼如下:

function checkClosure(){
    var str = 'rain-man';
    setTimeout(
        function(){ alert(str); } //這是一個匿名函數
    , 2000);
}
checkClosure();

這個例子看起來十分的簡單,仔細分析下它的執行過程還是有許多知識點的:checkClosure函數的執行是瞬間的(也許用時只是0.00001毫秒),在checkClosure的函數體內創建了一個變量str ,在checkClosure執行完畢之後str並沒有被釋放,這是因為setTimeout內的匿名函數存在這對str的引用。待到2秒後函數體內的匿名函數被執行完畢,str才被釋放。

範例二,最佳化程式碼

複製程式碼 程式碼如下:

function forTimeout(x, y){
    alert(x y);
}
function delay(x , y  , time){
    setTimeout('forTimeout('   x ','   y ')' , time);   
}
/**
 * 上面的delay函數十分難以閱讀,也不容易寫,但如果使用閉包就可以讓程式碼更清晰
 * function delay(x , y , time){
 *     setTimeout(
 *         function(){
 *             forTimeout(x , y)
 *         }         
 *     , time);  
 * }
 */
 

3、舉例
匿名函數最大的用途是建立閉包(這是JavaScript語言的特性之一),也可以建立命名空間,以減少全域變數的使用。

範例三:

複製程式碼 程式碼如下:

var oEvent = {};
(function(){
    var addEvent = function(){ /*程式碼的實作省略了*/ };
    function removeEvent(){}

    oEvent.addEvent = addEvent;
    oEvent.removeEvent = removeEvent;
})();

在這段程式碼中函數addEvent和removeEvent都是局部變量,但我們可以透過全域變數oEvent使用它,這大大減少了全域變數的使用,增強了網頁的安全性。 我們要使用此段程式碼:oEvent.addEvent(document.getElementById('box') , 'click' , function(){});

範例四:

複製程式碼 程式碼如下:

var rainman = (function(x , y){
    return x y;
})(2 , 3);
/**
 * 也可以寫成下面的形式,因為第一個括號只是幫助我們閱讀,但不建議使用下面這種書寫格式。
 * var rainman = function(x , y){
 *    return x y;
 * }(2 , 3);
 */

在這裡我們建立了一個變數rainman,並透過直接呼叫匿名函數初始化為5,這個小技巧有時十分實用。

範例五:

複製程式碼 程式碼如下:

var outer = null;
(function(){
    var one = 1;
    function inner (){
        one = 1;
        alert(one);
    }
    outer = inner;
})();
outer();    //2
outer();    //3
outer();    //4

這段程式碼中的變數one是一個局部變數(因為它被定義在一個函數之內),因此外部是不可以存取的。但這裡我們建立了inner函數,inner函數是可以存取變數one的;又將全域變數outer引用了inner,所以三次呼叫outer會彈出遞增的結果。

4、注意
4.1 閉包允許內層函數引用父函數中的變量,但是該變數是最終值

範例六:

複製程式碼 程式碼如下:

/**
 *
 *

     *    
  • 一個

  •  *    
  • 兩個

  •  *    

  •  *    
  • 一個

  •  *

 */

var lists = document.getElementsByTagName('li');
for(var i = 0 , len = lists.length ; i     lists[ i ].onmouseover = function(){
        alert(i);   
    };
}

你會發現當滑鼠移過每一個

  • 解決方法一:

    複製程式碼 程式碼如下:

    var lists = document.getElementsByTagName('li');
    for(var i = 0 , len = lists.length ; i     (function(index){
            lists[ index ].onmouseover = function(){
                alert(index);   
            };                   
        })(i);
    }

    解決方法二:

    複製程式碼 程式碼如下:

    var lists = document.getElementsByTagName('li');
    for(var i = 0, len = lists.length; i     lists[ i ].$$index = i;    //透過在Dom元素上綁定$$index屬性記錄下標
        lists[ i ].onmouseover = function(){
            alert(this.$$index);   
        };
    }

    解決方法三:

    複製程式碼 程式碼如下:

    function eventListener(list, index){
        list.onmouseover = function(){
            alert(index);
        };
    }
    var lists = document.getElementsByTagName('li');
    for(var i = 0 , len = lists.length ; i     eventListener(lists[ i ] , i);
    }

    4.2 記憶體外洩

    使用閉包十分容易造成瀏覽器的記憶體洩露,嚴重情況下會是瀏覽器掛死,有興趣的話可以參考:http://www.jb51.net/article/57404.htm

  • 相關標籤:
    來源:php.cn
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板