不久前的面試中,面試官開門見山問我閉包是什麼,我啞然。就像this同樣,可能給我幾道關於this的題目我會作,可是要我說說什麼是this,我還真不知道從何提及,爲了face之後一樣的問題,查閱了一些資料在此簡單作下記錄。誠然,樓主對於閉包的理解還處在初級階段...面試
簡單來講閉包擁有三個特性:閉包
1.函數嵌套函數
2.函數內部能夠引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收模塊化
閉包是指有權訪問另外一個函數做用域中的變量的函數,建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量。使用閉包有一個優勢,也是它的缺點,就是能夠把局部變量駐留在內存中,能夠避免使用全局變量。全局變量在每一個模塊均可調用,這勢必將是災難性的。(因此推薦使用私有的,封裝的局部變量。)通常函數執行完畢後,局部活動對象就被銷燬,內存中僅僅保存全局做用域。但閉包的狀況不一樣!函數
我以爲這段說明也很精彩:js裏的函數在運行結束以後,全部的過程當中產生的變量都會被銷燬(銷燬原則是無引用)
但在js的函數A裏定義一個函數B並在外部引用時,這條引用鏈上的變量都不會銷燬(即便A已經運行結束),這個函數B就叫作一個閉包。this
function fn() { var a = 0; function f() { console.log(a++); } return f; } var b = fn(); b(); // 0 b(); // 1 b(); // 2
接着來看上面的例子,這是一段經典的閉包代碼,咱們看看代碼都幹了些什麼。spa
首先要明確f函數便是所謂的閉包,咱們看到它嵌套在fn函數內,並且訪問了外部的變量a,同時console的結果也證實了變量a貯存在了內存中!爲何會這樣呢?緣由在於f被賦予給了一個全局變量b,致使始終存在在內存中,而f的存在必須依賴於fn,這致使fn也始終存在在內存中,因而變量a不會在執行後被垃圾回收機制回收。以上例子很好地避免了全局變量的使用,避免了全局變量的污染。code
閉包還有什麼用?繼續一個經典的例子:對象
<ul> <li>0</li> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> var lis = document.getElementsByTagName('li'); for(var i = 0; i < lis.length; i++) { ~function(i) { lis[i].onclick = function() { alert(i) }; }(i) } </script>
咱們都知道不使用閉包的話,每一個li彈出的數字會是同樣的,這時的閉包就能把i的值儲存在內存中。blog
閉包還可用於模塊化代碼,減小全局變量的污染:ip
var abc = (function(){ //abc爲外部匿名函數的返回值 var a = 1; return function(){ a++; alert(a); } })(); abc(); //2 abc(); //3
閉包還可用於設置私有成員:
var obj = function(){ var num = 0; function a() { num++; return num; } function b() { num++; return num; } return { a: a, b: b } }(); console.log(obj.a()); // 1 console.log(obj.b()); // 2
這樣就沒法修改num的值了,保護了私有成員。
我的感受閉包和當即執行函數有着剪不斷理還亂的關係啊...
樓主對於閉包的理解暫時到這裏了,若有不對或者補充之處還望留言~