由于本人是做[Java Web](http://lib.csdn.net/base/13 "Java Web知識庫")?開發的,對js只是存在很淺的理解,js閉包的概念很早就聽說了,但是一直都不明白是什么意思,今天準備梳理一下閉關的概念;
閉包(`closure`)是`[JavaScript](http://lib.csdn.net/base/18 "JavaScript知識庫")`語言的一個難點,也是它的特色,很多高級應用都要依靠閉包實現。
閉包的特性:
1.函數嵌套函數
2.函數內部可以引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收
## 閉包的定義及其優缺點
閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的最常見的方式就是在一個函數內創建另一個函數,通過另一個函數訪問這個函數的局部變量
閉包的缺點就是常駐內存,會增大內存使用量,使用不當很容易造成內存泄露。
閉包是`javascript`語言的一大特點,主要應用閉包場合主要是為了:設計私有的方法和變量。
一般函數執行完畢后,局部活動對象就被銷毀,內存中僅僅保存全局作用域。但閉包的情況不同!
嵌套函數的閉包:
~~~
function sum(){
var a=1;
return function(){
alert(a++)
};
}
var fun=sum();
fun(); //執行后a++,然后a還在
fun();
fun=null; //a被回收
~~~
閉包會使變量始終保存在內存中,如果不當使用會增大內存消耗。
##javascript的垃圾回收原理
(1)、在`javascript`中,如果一個對象不再被引用,那么這個對象就會被`GC`回收;?
(2)、如果兩個對象互相引用,而不再被第`3`者所引用,那么這兩個互相引用的對象也會被回收。
使用閉包的好處
那么使用閉包有什么好處呢?使用閉包的好處是:
~~~
全選復制放進筆記<script>
var abc = (function(){ //abc為外部匿名函數的返回值
var a = 1;
return function(){
a++;
alert(a);
}
})();
abc(); //2 ;調用一次abc函數,其實是調用里面內部函數的返回值
abc(); //3
</script>
~~~
## 五、私有成員的存在
~~~
var aaa=(function(){
var a=1;
function bbb(){
a++;
return a;
}
function ccc(){
a++;
return a;
}
return {
b:bbb, //為內部方法取一個別名 json結構
c:ccc
}
})();
alert(aaa.b()); //2
alert(aaa.c()); //3
~~~
## 六.使用匿名函數實現累加
我們先看看不使用匿名函數的情況下
~~~
function box(){
var age=100;
age++;
return age;
}
var b=box();
alert(b);
~~~
在看看使用匿名函數的情況
~~~
//使用匿名函數實現局部變量駐留內存中,從而實現累加
<script type="text/javascript">
function box(){
var age = 100;
return function(){ //匿名函數
age++;
return age;
};
}
var b = box();
alert(b());
~~~
過度使用閉包會導致性能的下降。函數里放匿名函數,則產生了閉包.在這種情況下我們最好不要使用閉包;如果使用了閉包要記得釋放引用;
~~~
b = null; //解除引用,等待垃圾回收
~~~
## 七、在循環中直接找到對應元素的索引
~~~
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title></title>
<script>
window.onload = function(){
var aLi = document.getElementsByTagName('li');
for (var i=0;i<aLi.length;i++){
(function(i){
aLi[i].onclick = function(){
alert(i);
};
})(i);
}
};
</script>
</head>
<body>
<ul>
<li>123</li>
<li>456</li>
<li>789</li>
</ul>
</body>
</html>
~~~
以上內容轉載自https://segmentfault.com/a/1190000000652891
閉包的深入理解:
閉包和匿名函數的兩個概念,上面說過閉包是指有權訪問另一個函數作用域中的變量的函數。創建閉包最簡單的方式,就是在一個函數內部創建一個匿名函數。
閉包與變量:
作用域鏈的這種配置機制引出了一個值得注意的副作用,即閉包只能取得包含函數中任何變量的最后一個值。閉包所保存的是整個變量對象,而不是某個特殊的變量。
~~~
function createArray(){
var array=new Array();
for(var i=0;i<10;i++){
array[i]=function(){
return i;
};
}
return array;
}
createArray();
~~~
這個函數會返回一個函數數值。表面上看,似乎每個函數都應該返回自己的索引值,即位置0的函數返回0,位置1的返回1.單實際上每個函數都返回10.因為每個函數的作用域鏈中都保存著這個函數的活動對象。所以他們引用的都是同一個變量i。當createArray創建后,變量i的值是10,此時每個函數都引用著保存變量i的同一個變量對象,所以在每個函數內部i的值都是10.我們可以通過匿名函數來讓閉包的行為符合預期
~~~
function createArray(){
var array=new Array();
for(var i=0;i<10;i++){
array[i]=function(num){
return function(){
return num
}
}(i);
}
return array;
}
~~~
在重寫了前面的函數后,每個函數就會返回各自不同的索引值了。在這個版本中,我們沒有直接把閉包賦值給數值,而是定義了一個匿名函數,并將立即執行該匿名函數的結果賦值給數組。這里的匿名函數有一個參數num,也就是最終的函數要返回的值。在調用每個匿名函數時。我們傳入了變量i.由于該函數時按值傳遞的,所以就會將i的當前值復制給參數num。而在這個匿名函數內部,又創建并返回了一個訪問num的閉包。這樣一來,result數組中的每個函數都有自己num變量的一個副本,因為就可以返回各自不同的數值了;
- 前言
- javascript基礎與定義
- JavaScript變量
- JavaScript變量二(數據類型,Number,String,Object)
- JavaScript傳參的問題
- JavaScript基本類型和引用類型的值
- JavaScript執行環境及作用域
- JavaScript垃圾收集
- JavaScript和JQuery和angularjs操作select
- 搞對象前,你得先有對象
- JavaScript數組
- JavaScript運行原理解析
- Jquery和angularjs獲取check框選中的值小技巧
- JavaScript函數表達式
- JavaScript的閉包理解
- JavaScript BOM
- JavaScritpt的DOM初探之Node(一)
- 為什么說DOM操作很慢
- jQuery性能優化