淺談javascript中的閉包

來源:互聯網
上載者:User

淺談javascript中的閉包

   Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對於那些使用傳統靜態語言C/C++的程式員來說是一個新的語言特性。本文將以例子入手來介紹Javascript閉包的語言特性,並結合一點 ECMAScript語言規範來使讀者可以更深入的理解閉包。

  很長一段時間不理解閉包,後來瞭解了範圍,以及this相關問題才理解了閉包相關知識。

  閉包(closure),也是面試題常客。簡單點來說就是函數嵌套函數。

  函數作為傳回值:

  ?

1

2

3

4

5

6

7

8

9

10

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。

  函數作為參數:

  ?

1

2

3

4

5

6

7

8

9

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代碼:

  ?

1

2

3

4

5

<ul>

<li>001</li>

<li>002</li>

<li>003</li>

</ul>

  js代碼:

  樣本 1:

  請看下面的代碼,運行後發現,無論點擊那個li,結果都是3了。

  ?

1

2

3

4

5

6

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:

  ?

1

2

3

4

5

aLi[i].onclick = (function(i){

return function(){

alert(i);

}

})(i);

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

  樣本 3:

  ?

1

2

3

4

5

6

7

for (var i = 0; i<aLi.length; i++) {

(function(i){

aLi[i].onclick = function(){

alert(i);

}

})(i);

}

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

  小米前端閉包面試題:

  ?

1

2

3

4

5

6

7

function repeat (func, times, wait) {

} //這個函數能返回一個新函數,比如這樣用

 

var repeatedFun = repeat(alert, 10, 5000)

//調用這個 repeatedFun ("hellworld")

 

//會alert十次 helloworld, 每次間隔5秒

  我的答案:

  ?

1

2

3

4

5

6

7

8

9

10

11

12

13

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閉包能夠有所協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.