萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> JavaScript 匿名函數和閉包介紹

JavaScript 匿名函數和閉包介紹

 匿名函數:沒有名字的函數;

閉包:可訪問一個函數作用域裡的變量的函數;

一 匿名函數

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // 普通函數 function box(){ // 函數名是box; return 'Lee'; } box(); // =>Lee; 調用函數; // 匿名函數 function(){ // 匿名函數,會報錯; return 'Lee'; } // 通過表達式自我執行 (function(name){ console.log(name); // =>Lee; })("Lee"); // "()"表示執行函數,並且可以傳參; // 把匿名函數賦值給變量 var box = function(){ // 將匿名函數賦給變量; return 'Lee'; }; console.log(box()); // 調用方式和函數調用相似; // 函數裡的匿名函數 function box(){ return function(name){ // 函數裡的匿名函數,產生閉包; return name; }; }; console.log(box()("Lee")); // 函數box()調用匿名函數,並傳參;

二 閉包

閉包:有權訪問另一個函數作用域中的變量的函數;
創建閉包的常見方式:在一個函數內部創建另一個函數;通過另一個函數訪問這個函數的局部變量;

1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 通過閉包可以返回局部變量 function box(){ var user = 'Lee'; return function(){ // 通過匿名函數返回box()的局部變量user; return user; }; } console.log(box()()); // =>Lee; 直接調用box()()來獲得匿名函數的返回值;   var b = box(); console.log(b()); // =>Lee; 另一種調用匿名函數方式;   // 優點:可以把局部變量駐留在內存中,可以避免使用全局變量; // (全局變量污染導致應用程序不可預測性,每個模塊都可調用必將引來災難;所以推薦使用私有的,封裝的局部變量); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 // 缺點: // 通過全局變量來累加 var age = 100; // 全局變量; function box(){ age++; // 模塊級可以調用全局變量,進行累加; }; box(); // 執行函數,累加一次; console.log(age); // =>101; 輸出全局變量; box(); // 執行函數,累加一次; console.log(age); // =>102; 輸出全局變量; // 通過局部變量無法實現累加 function box(){ var age = 100; age++; // 實現累加; return age; } console.log(box()); // =>101; console.log(box()); // =>101; 無法實現累加,因為第二次調用函數時,函數內部變量age又被初始化了;   // 通過閉包可以實現局部變量的累加 function box(){ var age = 100; return function(){ // 匿名函數內實現累加; age++; return age; // 並返回累加後的變量; }; // 此時box()函數的局部變量age的值已經被修改為累加後的值; } var b = box(); // 給box()函數賦值給變量; console.log(b()); // =>101; 調用匿名函數,累加一次; console.log(b()); // =>102; 第二次調用匿名函數,累加兩次;   // PS:由於閉包裡作用域返回的局部變量資源不會被立刻銷毀回收,所以可能會占用更多的內存;所以過度使用閉包會導致性能下降;(將閉包引用在"私有作用域"中即可實現變量銷毀) // 作用域鏈的機制導致一個問題,在循環中裡的匿名函數取得的任何變量都是最後一個值; ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 // 循環裡包含匿名函數 function box(){ var arr = []; for(var i=0; i<5; i++){ // 當聲明變量i=5時,循環停止;而此時循環裡的變量i==5; arr[i] = function(){ // arr[i]得到的只是沒有執行的匿名函數function(){}; return i; }; }; return arr; // arr = [function,function,function,function,function]; } var b = box(); // =>[function,function,function,function,function]; 得到函數box()返回的數組arr; console.log(b.length); // =>5; 得到函數集合數組長度; for(var i=0; i<b.length; i++){ console.log(box()[i]()); // =>5,5,5,5,5; 輸出每個函數的值,都是最後一個值; } // 上面的例子輸出的結果都是5,也就是循環後得到的最大i值; // 因為b[i]調用的是匿名函數,匿名函數並沒有自我執行,等到調用的時候,box()已執行完畢,i早已變成5;   // 循環裡包含匿名函數-改1,自我執行匿名函數 function box(){ var arr = []; for(var i=0; i<5; i++){ arr[i] = (function(num){ // arr[i]得到的是匿名函數執行後的結果數值0-4; return num; })(i); // 自我執行並傳參; } return arr; } var b = box(); // =>[0,1,2,3,4]; 此時b代表box()返回的數組; for (var i = 0; i < b.length; i++) { console.log(b[i]); // 0 1 2 3 4; 這裡返回的是數值; }; // 例子中,我們讓匿名函數進行自我執行,導致最終返回給a[i]的是數組而不是函數了;最終導致b[0]-b[4]中保留了0,1,2,3,4的值;   // 循環裡包含匿名函數-改2,匿名函數裡再做個匿名函數; function box(){ var arr = []; for(var i=0; i<5; i++){ arr[i
copyright © 萬盛學電腦網 all rights reserved