前言
Javascript閉包在學習過程中一般較難理解,本文從什么是閉包,常見閉包示例,閉包作用,閉包應用及閉包問題等方面來介紹閉包,希望能給大家帶來更深層次的認識,有不恰當之處請指出,謝謝。
一、什么是閉包?
閉包是指一個嵌套的內部(子)函數引用了父函數作用域中數據的函數,這就產生了閉包。
關鍵理解:
1. 產生閉包必須要有嵌套函數
2. 閉包是函數,并是嵌套的內部函數
3. 閉包內部函數必須要引用父函數作用域中數據
如果不滿足以上條件,則不能產生閉包,接下來示例說明。
1.1閉包滿足條件代碼
1
2
3
4
5
6
7
8
9
|
<script> function person(){ var name= 'marshal' ; function student(){ //聲明子函數 console.log(name); //引用父函數作用域的變量name } } person(); //函數執行,產生閉包 </script> |
1.2閉包產生時機
1
2
3
4
5
6
7
8
9
10
|
<script> function person(){ var name= 'marshal' ; //js執行此行時,產生閉包 function student(){ //聲明子函數 console.log(name); //引用父函數作用域的變量name } student(); //內部函數在外部函數調用 } person(); //函數執行,雖滿足閉包條件,但未產生閉包 </script> |
閉包產生時機:嵌套子函數代碼塊有引用父函數作用域的數據,并該嵌套子函數要執行前,創建上下文時產生閉包。或者簡單說該該嵌套子函數在外部被執行時,此刻產生了閉包。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> function person(){ var name= 'marshal' ; function student(){ console.log(name); //該方法代碼內為閉包代碼 } return student; } var p=person(); //因創建子函數對像,此時產生第一次閉包,并將子函數student返回給p,由于p沒有消失,子函數引用的變量name,一直在內存在存儲,直到將p=null,進行回收 p(); //執行子函數的閉包代碼塊,輸出"marhsal" p(); //第二次執行子函數的閉包代碼塊,輸出"marhsal" person(); //第二次創建子函數調對象,此時產生第二次閉包,但不執行子函數student代碼塊 </script> |
二、常見閉包示例
2.1 子函數做為實參傳遞
1
2
3
4
5
6
7
8
|
<script> function setTimeoutTest(message,time){ setTimeout( function (){ alert(message); //嵌套子函數引用父函數變量message,產生閉包 },time); } setTimeoutTest( '提示信息' ,1000); </script> |
2.2 計數器使用(函數返回)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
< script > function count(){ var i=1; function add(){ i++; console.log(i); } return add; } var c=count();//生產閉包 c();//2 c();//3 c();//4 </ script > |
三、閉包作用
3.1 閉包作用
1)子函數引用父函數的變量或函數,生命周期延長
2)其變量或函數一直存在,外部可以訪問函數內部的值
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> function count(){ var i=1; function add(){ i++; console.log(i); } return add; } var c=count(); c(); //2 c(); //3 i的生命周期延長 </script> |
四、閉包應用
4.1 自定義封裝js代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
外部js代碼 out.js 實現自加與自減 ( function count(){ var i=1; function add(){ i++; console.log(i); } function subtract(){ i-- console.log(i); } window.count={ add:add, subtract:subtract } })(); |
1
2
3
4
5
6
7
|
引用 out.js代碼 <script src=out.js></script> <script> count.add(); //2 count.subtract(); //1 count.subtract(); //0 </script> |
五、閉包問題
5.1 閉包與this
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> var name= "marshal" ; //創建全局變量 var person={ name: "leo" , getName: function (){ //返回匿名函數 return function (){ //返回this.name return this .name; //返回字符串 } } }; alert(person.getName()()); //輸出marshal,內部函數不可能直接訪問外部函數this </script> |
解決方法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script> var name= "marshal" ; var person={ name: "leo" , getName: function (){ var that= this ; //把this保存到閉包可以訪問的另一個變量中 return function (){ return that.name; } } }; alert(person.getName()()); //that 指向person,而不是window </script> |
5.2 內存泄露
在使用閉包時,因變量一直存在,需要解除對象的引用,將對象設置為null, 從而確保其內存在適當時候可以被回收。
到此這篇關于關于Javascript閉包與應用的詳解的文章就介紹到這了,更多相關js閉包與應用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/Marshaljun/article/details/115785867