javascript
彻底了解JS中难懂的闭包
來自:一只有趣的程序猿?|?責編:樂樂
鏈接:jianshu.com/p/2fa4e8a1eaf9
閉包的定義
閉包是指有權訪問另一個函數作用域中的變量的函數。(JS高級程序設計)
看到這紅寶書上關于閉包的解釋,起初一臉懵逼,讀懂之后其實并不難。
要徹底了解閉包,首先必須了解下面的幾個概念:
執行環境:每個函數都有自己的執行環境。當執行函數時,函數的環境就會被推入一個環境棧中。而在函數執行后,棧將其環境彈出,把控制權返回給之前的執行環境。
變量對象:每個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保存在這個對象中。當執行函數時,變量對象會變成活動對象。
作用域鏈:當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈。作用域鏈的用途,是保證對執行環境有權訪問的所有變量和函數的有序訪問。作用域鏈的前端,始終都是當前執行的代碼所
在環境的變量對象。如果這個環境是函數,則將其活動對象作為變量對象。
執行環境和變量對象的概念容易理解,但是怎么理解作用域鏈呢。可以參考下圖:
理解作用域鏈
可以看成是同心圓結構,每一層假設是一個函數,上面都擁有與此層函數關聯的變量對象;假設當執行到最里面那個函數,那么作用域鏈可以看做是圖中一條由內到外的線,最前端的就是它本身,最后端就是全局執行環境。
那么它有什么用呢,就是當你訪問一個變量的時候,就會沿著作用域鏈一層層往外查找,直到找到為止,如果到了最外層即全局執行環境下還沒找到則報錯。
閉包的實現
下面通過具體例子來解釋:
function?a()?{var?text?=?'呵呵噠';return?function?()?{console.log(text);} } var?b?=?a(); b();當a()函數被執行后返回了一個匿名函數,這個匿名函數的作用域鏈上有引用到a()執行環境的活動對象屬性text(不知道活動對象是什么的請看上面變量對象的解釋)。
a()函數執行完就馬上被銷毀了,但是這個函數的變量對象仍然被b所引用,所以它的變量對象不會被垃圾回收機制處理掉,而是會留在內存中。這就形成了一個閉包。最后執行b()依然能讀取到已經被銷毀的a函數的定義的text變量。
我們換個更清晰的例子:
function?a()?{var?i?=?0;return?function?()?{console.log(i++);} } var?b?=?a(); b();????//0 b();????//1 b();????//2這個例子三次調用b()會分別輸出0、 1、 2,是因為a()的變量對象被return的閉包函數引用著,所以i會一直留在內存中,并只能被閉包函數所訪問。這個閉包函數被賦值給了b,所以b()能對i變量進行自增計算。
閉包的作用
什么,你問我閉包有什么用?
好處就是隱藏變量,然后搭起一條溝通的橋,閉包可以間接操作這個隱藏變量;并且讓這個變量留在內存中而不會污染到全局變量。
壞處呢消耗內存,如果一直不釋放這個閉包就會一直占用著內存。那要怎么釋放呢?很簡單,和函數一樣賦值null就可以了。(b = null)
總結
以上是生活随笔為你收集整理的彻底了解JS中难懂的闭包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 同步IO和异步IO的理解
- 下一篇: virtualbox增强功能-VBoxG