閉包其實就是乙個函式,什麼樣的函式?能夠訪問另乙個函式作用域中變數的函式。
在回答這個問題之前,我先提乙個假設,我們都知道在內部的函式可以訪問外部函式的變數,假設現在就是有這麼乙個需要,需要外部環境來訪問函式的內部變數,怎麼辦?這時就要用到閉包,這就要牽扯到閉包的實現原理,即作用域鏈的工作。每當函式建立時,js底層都會在其執行環境下建立乙個作用域鏈,這個作用域鏈可以理解為乙個指標鍊錶,指向每個函式的活動物件(活動物件中儲存著區域性變數),並且這個作用域鏈由內函式向外函式擴散直到全域性變數物件。父函式內部返回閉包,在外部環境呼叫父函式後,這時父函式執行完畢,作用域鏈銷毀,但是父函式的活動物件沒有銷毀,任然留在記憶體中,為什麼?就是因為我返回的閉包的作用域鏈中有指向父函式活動物件的引用。這樣,在外部環境下,返回的閉包就會沿著自己的作用域鏈去尋找訪問的值,就實現了在外部環境下訪問函式的內部變數
首先先給大家兩個簡單的**
function createfunctions();
} return result;
}
在這段**中,直觀感覺返回的result是乙個返回i值的乙個函式,結果應該是0-9,但是結果都是10。
在這裡我想說兩個問題,第一js沒有塊級作用域,i變數會被繫結到create函式的活動物件中。第二在執行返回的閉包後,此時沿著作用域鏈尋找到的 i 值都是10.這個 i 值是createfunctions函式活動物件中儲存,0-9都在這個活動物件**現過,但是最終讓10覆蓋掉了,所以每乙個閉包訪問到的 i 都是10.
那麼如何修改呢?
function createfunctions();
}(i);
} return result;
}
在重寫了前面的
createfunctions()
函式後,每個函式就會返回各自不同的索引值了。在這個版本中,我們沒有直接把閉包賦值給陣列,而是定義了乙個匿名函式,並將立即執行該匿名函式的結果賦給陣列。這裡的匿名函式有乙個引數 num
,也就是最終的函式要返回的值。在呼叫每個匿名函式時,我們傳入了變數 i
。由於函式引數是按值傳遞的,所以就會將變數
i 的當前值複製給引數
num。而在這個匿名函式內部,又建立並返回了乙個訪問 num
的閉包。這樣一來,
result
陣列中的每個函式都有自己num 變數的乙個副本,因此就可以返回各自不同的數值了。也就是說,這個閉包陣列所訪問那個匿名函式中的num其實都是來自不同的活動物件,每個活動物件所儲存的num值都不同,所以才會返回0-9.
JS中的閉包理解
一 變數的作用域 變數的作用域兩種 全域性變數和區域性變數。函式內部可以直接讀取全域性變數。在函式外部自然無法讀取函式內的區域性變數。函式內部宣告變數的時候,一定要使用var命令。如果不用的話,實際上宣告了乙個全域性變數 二 如何從外部讀取區域性變數?那就是在函式的內部,再定義乙個函式。functi...
JS閉包理解
下圖例項 body ul li 1 li li 2 li li 3 li ul body html script vara document.getelementsbytagname li for vari 0 i a.length i i 如何從外部讀取區域性變數 functionvisitinn...
JS閉包理解
js閉包理解 在很多面試題中都會問什麼是js的閉包,為什麼需要使用閉包,使用閉包的優缺點!我在面試其他人的時候也喜歡問這個問題,回答的也是千奇百怪,現在就總結一下我對閉包的理解。閉包是一種概念,這種概念比較複雜,很多地方的定義不盡相同,我的理解是 閉包是能讀取函式內部變數的函式,也就是定義在函式內部...