在理解js閉包函式之前我們應該先要了解什麼是js函式?
js函式中可以分為兩個階段:
函式定義階段注:在特殊情況下函式執行完畢,新開闢出來的空間也不會銷毀1. 在記憶體中開闢乙個儲存空間
2. 把函式體內的**當作字串一摸一樣的放在這個空間中
=> 碰到的所有變數都不進行解析
3. 把這個空間位址賦值給函式名(變數名)
=>函式呼叫階段
1. 按照函式名(變數名)找到對應的儲存空間
2. 重新開闢乙個函式執行空間
3. 在這個執行空間裡面進行形參賦值
4. 在這個執行空間裡面進行預解析
5. 把函式儲存空間的**複製乙份到執行空間裡面執行一遍
6. 執行完畢之後, 這個開闢出來的執行空間銷毀
如下面這段**函式的執行空間就不會銷毀
functionfn(
)var res =fn(
)
上面這段** :
res 接受的就是 函式fn 返回的那個複雜資料型別(乙個陣列)res 接受的是 函式fn 執行空間裡面那個陣列的位址
既res 接受的是 函式fn 的執行空間內的乙個陣列
+ 只要這個陣列還存在, 就表示這個函式執行空間沒有銷毀
+ 因為一旦函式執行空間銷毀了, 那麼這個陣列也就沒有了
+ 所以這個函式執行空間不能銷毀
注:當需要銷毀這段空間的時候需要手動設定 res=null
=> 閉包的生成有三個必要條件(缺一不可)
1. 在函式 a 內部直接或者間接返回乙個函式 b
2. b 函式內部使用著 a 函式的私有變數(私有資料)
3. a 函式外部有乙個變數接受著函式 b(a函式把b函式當做返回值)
: 形成了乙個不會銷毀的函式空間
閉包空間
+ 現在我們管這個不會銷毀的 a 函式的執行空間叫做 閉包空間
+ 把函式 a 裡面返回的 函式 b, 叫做函式a 的 閉包函式
+ 官方給的定義有一句話: 閉包 => 函式內部的函式
如下面這段**: 函式作為返回值
functiona(
)}var res =a(
)
在這段**中,a()中的返回值是乙個函式b(),這個函式在a()作用域內部,所以它可以獲取a()作用域下變數num的值,將這個值作為返回值賦給全域性作用域下的變數res,實現了在全域性變數下獲取到區域性變數中的變數的值.
再來看乙個閉包的經典例子:
functionfn(
)}var res =fn(
)res()
//1 6
res(
)//1 7
一般情況下,在函式fn執行完後,就應該連同它裡面的變數一同被銷毀,但是在這個例中,函式b()作為fn的返回值被賦值給了res,這時候相當於res=b(),並且函式b()內部引用著fn裡的變數num,所以變數num無法被銷毀,而變數n是每次被呼叫時新建立的,所以每次res()執行完後它就把屬於自己的變數連同自己一起銷毀,於是乎最後就剩下孤零零的num,於是這裡就產生了記憶體消耗的問題.
綜上所訴利弊問題:
利:1、保護函式內的變數安全 ,實現封裝,防止變數流入其他環境發生命名衝突2、在記憶體中維持乙個變數,可以做快取(但使用多了同時也是一項缺點,消耗記憶體)
3、匿名自執行函式可以減少記憶體消耗
弊:1、有一點上面已經有體現了,就是被引用的私有變數不能被銷毀,增大了記憶體消耗,造成記憶體洩漏,解決方法是可以在使用完變數後手動為它賦值為null;
2、其次由於閉包涉及跨域訪問,所以會導致效能損失,我們可以通過把跨作用域變數儲存在區域性變數中,然後直接訪問區域性變數,來減輕對執行速度的影響
如何理解閉包?
1 定義和用法 當乙個函式的返回值是另乙個函式,而返回的那個函式如果呼叫了其父函式內部的其它變數,如果返回的這個函式在外部被執行,就產生了閉包。2 表現形式 使函式外部能夠呼叫函式內部定義的變數。3 例項如下 1 根據作用域鏈的規則,底層作用域沒有宣告的變數,會向上一級找,找到就返回,沒找到就一直找...
如何理解閉包?
1 閉包是js的副產品,當你的函式訪問函式外部的變數的時候,js形成閉包,閉包實際上是作用域的逐級查詢,當b函式執行完成之後銷毀,此時a函式的被b函式引用,值並沒有被銷毀而是在記憶體中儲存了下來 function a return b var c a c 1 c 2 2 閉包應用優點 當想要提公升效...
python閉包怎麼理解 Python 閉包的理解
很多函式型的語言都有閉包這一概念,比如python的兄弟js。人們剛聽到閉包這一概念總會覺得它很晦澀,難以理解。其實不然,主要是他的名字起得太抽象了,讓人誤以為很難。下面舉乙個例子 coding utf 8 def foo nums 0 5 for i in range 5 nums i lambd...