首頁 >web前端 >js教程 >淺談javascript中的閉包_javascript技巧

淺談javascript中的閉包_javascript技巧

WBOY
WBOY原創
2016-05-16 15:59:251136瀏覽

很長一段時間不理解閉包,後來了解了作用域,以及this相關問題才理解了閉包相關知識。
閉包(closure),也是面試題常客。簡單點來說就是函數巢狀函數。

函數作為回傳值:

function foo () {
  var a = 1;
  return function () {
   a++;
   console.log(a);
  }
}
var aaa = foo();
aaa(); //2
aaa(); //3

其實這個程式碼不難理解,aaa是指向foo()返回的一個新函數,但是在這個函數裡面引用了a變量,所以當執行完foo函數時,變數a還存在內存中不釋放。即a分別為2和3。

函數作為參數:

var a = 10;
function foo () {
console.log(a);
}
function aaa(fn) {
 var a = 100;
 fn();
}
aaa(foo);

照我以前的理解,當執行在aaa函數裡面執行fn函數,那麼如果自身沒有a變量,就去父級作用域找a變量,此處是100,那結果是100嗎?

可惜答案不是,在這裡結果是10,王福朋老師的部落格講的比較好,他說要去創建這個函數的作用域取值,而不是「父作用域」。

閉包的使用場景

因為本人還比較菜鳥,在這裡取一個簡單例子。當點選li的時候彈出li在ul中所處的位置即索引值。

html代碼:

<ul>
  <li>001</li>
  <li>002</li>
  <li>003</li>
</ul>

js程式碼:

範例 1:
請看下面的程式碼,運行後發現,無論點擊那個li,結果都是3了。

var aLi = document.getElementsByTagName('li');
for (var i = 0; i<aLi.length; i++) {
  aLi[i].onclick = function() {
   alert(i);
  }
}

因為在匿名函數裡面並沒有i變量,所以當for結束後,我們再去點擊頁面的li標籤,此時i早就是3了。

範例 2:

aLi[i].onclick = (function(i){
    return function(){
      alert(i);
    }
  })(i);

這次的做法是把函數當回傳值,透過自執行函數的參數,把變數i傳進去,然後因為回傳函數要引用這個i變量,所以當for迴圈結束也不會釋放i變數。即在記憶體中保存了i變數的值。基於這樣的原理,很容易在低版本ie中造成記憶體外洩。

範例 3:

for (var i = 0; i<aLi.length; i++) {
  (function(i){
    aLi[i].onclick = function(){
      alert(i);
    }
  })(i);
}

這個原理和上面大同小異。

小米前端閉包面試題:

function repeat (func, times, wait) {
} //这个函数能返回一个新函数,比如这样用

var repeatedFun = repeat(alert, 10, 5000)
//调用这个 repeatedFun ("hellworld")

//会alert十次 helloworld, 每次间隔5秒

我的答案:

function repeat (func, times, wait) {
  return function(str) {
    while (times >0) {
      setTimeout(function(){
        func(str);
      },wait);
      times--;
    }
  }
}

var repeatedFun = repeat(alert, 10, 100);
repeatedFun ("hellworld");

以上所述就是本文的全部內容了,希望對大家學習javascript閉包能夠有所幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn