javascript匿名函數和閉包

一.匿名函數數組

匿名函數就是沒有名字的函數。閉包

//普通函數
function laber() {                            //函數名是laber
    return 'momo';
}
//匿名函數
function () {                                //匿名函數,會報錯
    return 'momo';
}
//經過表達式自我執行
(function laber() {                            //封裝成表達式
    alert('momo');
})();                                        //()表示執行函數,而且傳參

//把匿名函數賦值給變量
var laber = function () {                        //將匿名函數賦給變量
    return 'momo';
};
alert(laber());                                //調用方式和函數調用類似

//函數裏的匿名函數
function laber() {
    return function () {                        //函數裏的匿名函數,產生閉包
        return 'momo';
    }
}
alert(laber()());                                //調用匿名函數

二.閉包函數

閉包是指有權訪問另外一個函數做用域中的變量的函數,建立閉包的常見的方式,就是在一個函數內部建立另外一個函數,經過另外一個函數訪問這個函數的局部變量。性能

//經過閉包能夠返回局部變量
function laber() {
    var name= 'momo';
    return function () {                        //經過匿名函數返回laber()局部變量
        return name;
    };
}
alert(laber()());                                //經過laber()()來直接調用匿名函數返回值

var b = laber();
alert(b());                                    //另外一種調用匿名函數返回值

使用閉包有一個優勢,也是它的缺點:就是能夠把局部變量駐留在內存中,能夠避免使用全局變量。(全局變量污染致使應用程序不可預測性,每一個模塊均可調用必將引來災難,因此推薦使用私有的,封裝的局部變量)this

//經過全局變量來累加spa

var age = 100;                                //全局變量
function laber() {
    age ++;                                //模塊級能夠調用全局變量,進行累加
}
laber();                                    //執行函數,累加了
alert(age);                                //輸出全局變量

//經過局部變量沒法實現累加code

function laber() {
    var age = 100;
    age ++;                                //累加
    return age;
}

alert(laber));                                //101
alert(laber());                                //101,沒法實現,由於又被初始化了

//經過閉包能夠實現局部變量的累加對象

function laber() {
    var age = 100;
    return function () {
        age ++;
        return age;
    }
}
var b = laber();                                //得到函數
alert(b());                                    //調用匿名函數
alert(b());                                    //第二次調用匿名函數,實現累加

因爲閉包裏做用域返回的局部變量資源不會被馬上銷燬回收,因此可能會佔用更多的內存。過分使用閉包會致使性能降低,建議在很是有必要的時候才使用閉包。blog

做用域鏈的機制致使一個問題,在循環中裏的匿名函數取得的任何變量都是最後一個值。內存

//循環裏包含匿名函數

function laber() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = function () {
            return i;
        };
    }
    return arr;
}
var b = laber();                                //獲得函數數組
alert(b.length);                                //獲得函數集合長度
for (var i = 0; i < b.length; i++) {
    alert(b[i]());                            //輸出每一個函數的值,都是最後一個值
}

上面的例子輸出的結果都是5,也就是循環後獲得的最大的i值。由於b[i]調用的是匿名函數,匿名函數並無自我執行,等到調用的時候,laber()已執行完畢,i早已變成5,因此最終的結果就是55

//循環裏包含匿名函數-1,自我執行匿名函數

function laber() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = (function (num) {            //自我執行
            return num;
        })(i);                            //而且傳參
    }
    return arr;
}
var b = laber();                    
for (var i = 0; i < b.length; i++) {
    alert(b[i]);                            //這裏返回的是數組,直接打印便可
}

1中,咱們讓匿名函數進行自我執行,致使最終返回給a[i]的是數組而不是函數了。最終致使b[0]-b[4]中保留了0,1,2,3,4的值。

//循環裏包含匿名函數-2,匿名函數下再作個匿名函數

function laber() {
    var arr = [];
    for (var i = 0; i < 5; i++) {
        arr[i] = (function (num) {
            return function () {                //直接返回值,改2變成返回函數
                return num;                //原理和改1同樣
            }
        })(i);
    }
    return arr;
}

var b = laber();                    
for (var i = 0; i < b.length; i++) {
    alert(b[i]());                            //這裏經過b[i]()函數調用便可
}

1和改2中,咱們經過匿名函數自我執行,當即把結果賦值給a[i]。每個i,是調用方經過按值傳遞的,因此最終返回的都是指定的遞增的i。而不是laber()函數裏的i

關於this對象

在閉包中使用this對象也可能會致使一些問題,this對象是在運行時基於函數的執行環境綁定的,若是this在全局範圍就是window,若是在對象內部就指向這個對象。而閉包卻在運行時指向window的,由於閉包並不屬於這個對象的屬性或方法。

相關文章
相關標籤/搜索