什麼是閉包?本文主要和大家分享JavaScript閉包基礎,包括JavaScript閉包定義和用法,希望能幫助大家。
書上是這樣定義閉包的:
有權存取另一個函數作用域中變數的函數。
舉一個例子:
function test(){ var a = 1; var b = function(){ return a; }; return b; } var c = test(); console.log(c()); //1
這裡c是直接得到了b這個函數表達式,但是呼叫c之後可以得到test的局部變數a的值1,也就是c它存取到了test作用域中的變數。
其實我初學的時候一直不清楚閉包的意思,因為我感覺這種情況是理所當然的,噗,後來才知道原來就是說這個啊。
究其根本,是因為b代表的函數包含test的作用域。
在某個函數被呼叫時會做下面這些事:
建立一個執行環境。
建立對應的作用域鏈(複製函數的[[Scope]]來完成)。
初始化函數的活動物件(arguments和其他命名參數),並被推入作用域最頂端。
而在作用域鏈中,外部函數的活動物件總是處於第二位,外部函數的外部函數的活動物件處於第三位...直到作為作用域鏈終點的全域執行環境。
舉個栗子
function test(value1,value2){ if(value1 < value2) return -1; return 0; } var result = test(5,10);
以上首先定義了test函數,又在全域作用域中呼叫它。
第一次呼叫時,會建立一個包含this、arguments、value1和value2的活動物件。
全域執行環境的變數(this、result、test)則處於test執行環境作用域鏈中的第二位。
每個執行環境都有一個表示變數的對象,稱為變數物件。
全域環境的變數物件一直存在,test()函數局部環境的變數物件只有在執行的時候會存在。
函數的作用域鍊是保存在內部的[[Scope]]屬性中。
作用域本質是一個指標列表,只保存引用。
以下是最初的栗子中test()的原型內容:
#匿名函數執行結束後,它的執行環境被銷毀了,但是傳回的活動物件沒有消失,所以閉包也不會消失,依舊存在記憶體中,如果給這個物件賦值null,就可以解除關係。
讓我們瞅瞅這段熟悉的程式碼:
function test(){ var result = new Array(); for(var i=0;i<10;i++){ result[i] = function(){ return i; } } return result; }
這個函數的實際結果是每個函數都回傳了10,因為它們實際的i都是同一個。
解決方法是用匿名函數:
function test(){ var result = new Array(); for(var i=0;i<10;i++){ result[i] = function(num)( return function(){ return num; } }(i); } return result; }
由於中間多加上了一層,即每次把一個num值傳入,所以內部的函數是形成了各自num的閉包,於是就沒有像之前一樣共用了。
相關推薦:
以上是JavaScript閉包基礎的詳細內容。更多資訊請關注PHP中文網其他相關文章!