讓我們一起來學習一下什麼是javascript的閉包
什麼是閉包: 閉包是一個存在內部函數的引用關系。 該引用指向的是外部函數的局部變量對象(前提是內部函數使用瞭外部函數的局部變量) 閉包的作用: 延長外部函數變量對象的生命周期 使用閉包能夠間接的從函數外部訪問函數內部的私有變量
一、常見的閉包
function outer() { var a = 1 function inner() { console.log(a) //1 } inner() } outer()
二、實例詳解
function createFunc() { var result = new Array() for (var i = 0; i < 10; i++) { result[i] = function () { console.log(i) } } return result } var result = createFunc() result[0]() //10 result[1]() //10 result[2]() //10 result[3]() //10 result[4]() //10 result[5]() //10 result[6]() //10 result[7]() //10
首先在代碼執行前,會先創建一個全局的對象,其中包含著全局的屬性,並且將其放入全局上下文作用域鏈頂端,並且也將其放入每一個函數的作用域鏈頂端。以這個例子為例。如圖所示
在初始化結束後,開始執行代碼,此時就會創建一個新的對象,叫做Active Object,其中放入一些參數,並且將其壓入createFunc函數的作用域鏈中。
因為在createFunc中仍然定義函數result[i]..,所以在執行代碼前,該函數會形成作用域鏈。
此時開始執行createFunc函數,當指向完畢後,createFunc中的作用域鏈表現為。如下圖所示。此時result為一個數組。並且Active object已經從createFunc作用域鏈的頂部刪除。
此時開始執行result[0](這裡以result[0]為例,其他的一樣),此時執行result[0]之前,應該創建一個新的Active object
對象,將其放入result[0]
執行作用域棧中。如圖所示
此時函數執行中需要訪問i,但是在active object並不存在i,所以此時需要沿著作用域鏈進行查找,在createFunc中找到i,並且i的值為10,所以最終打印的值都是10。在createFunc執行完畢後,其創建的對象並沒有被垃圾回收掉,因為在result[0]中的i依然保持對該對象的引用。
這個例子的解決方法如下所示,就是設置一個立即執行函數,每一個下標對應的函數,都是立即執行函數,當立即執行函數執行時,每一個函數的上下文對象中都會存在為正確的下標值。
function createFunc() { var result = new Array() for (var i = 0; i < 10; i++) { result[i] = (function (num) { return function() { console.log(num) } })(i) } return result } var result = createFunc() result[0]() //0 result[1]() //1 result[2]() //2 result[3]() //3 result[4]() //4 result[5]() //5 result[6]() //6 result[7]() //7
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- JavaScript的引用數據類型你瞭解多少
- JS 5高階函數分享
- 淺析JavaScript中的特殊函數及用法小結
- JavaScript數組及非數組對象的深淺克隆詳解原理
- 詳解JavaScript閉包問題