javascript
JavaScript中的闭包
什么是閉包?
當(dāng)函數(shù)可以記住并訪問(wèn)所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行的。
下面用一些代碼來(lái)解釋這個(gè)定義:
這是閉包嗎?
技術(shù)上來(lái)講,也許是。但根據(jù)前面的定義,確切地說(shuō)并不是。最準(zhǔn)確地來(lái)解釋 bar() 對(duì) a 的應(yīng)用方法是詞法作用域的查找規(guī)則(即在 bar() 的函數(shù)作用域中無(wú)法找到 a,則向上一級(jí)所嵌套的 foo() 的作用域中查找),而這些規(guī)則只是閉包的一部分。
下面再看一段代碼,清晰地展示了閉包:
函數(shù) bar() 的詞法作用域能夠訪問(wèn) foo() 的內(nèi)部作用域,然后將 bar() 函數(shù)本身作為一個(gè)值類型進(jìn)行傳遞。在這段代碼中,我們將 bar 所引用的函數(shù)對(duì)象本身作為返回值。在 foo() 執(zhí)行后,其返回值賦值給變量 baz 并調(diào)用 baz(),實(shí)際上只是通過(guò)不同的標(biāo)識(shí)符引用調(diào)用了內(nèi)部函數(shù) bar()。
在 foo() 執(zhí)行后,通常會(huì)期待 foo() 的整個(gè)內(nèi)部作用域都被銷毀。而閉包的神奇之處可以阻止作用域被銷毀,被回收。那么是誰(shuí)再使用這個(gè)內(nèi)部作用域?是 bar() 本身在使用。bar() 擁有覆蓋 foo() 內(nèi)部作用域的閉包,使得該作用域能夠一直存活,以供 bar() 在之后任何時(shí)間進(jìn)行引用。這個(gè)引用就叫做閉包。
再據(jù)兩個(gè)例子:
循環(huán)和閉包
先看下面的例子:
for(var i=1; i<=5; i++){setTimeout(function timer() {console.log(i);},i*1000); }這段代碼在運(yùn)行時(shí)會(huì)以每秒一次的頻率輸出五次6.為什么會(huì)這樣呢?
首先解釋6是怎么來(lái)的。這個(gè)循環(huán)的終止條件是 i<=5。條件首次成立時(shí) i 的值是6.因此,輸出顯示的是循環(huán)結(jié)束時(shí) i 的最終值。
延遲函數(shù)的回調(diào)會(huì)在循環(huán)結(jié)束時(shí)才執(zhí)行,當(dāng)定時(shí)器運(yùn)行時(shí)即使每個(gè)迭代中執(zhí)行的是 setTimeout(..,0),所有的回調(diào)函數(shù)依然是在勛魂結(jié)束后才會(huì)執(zhí)行,因此每次都輸出6.根據(jù)作用域的工作原理,實(shí)際情況是盡管循環(huán)中的五個(gè)函數(shù)是在各個(gè)迭代中分別定義的,但是它們都是被封閉在一個(gè)共享的全局作用域中,因此實(shí)際上只有一個(gè) i。
再看下一個(gè)代碼,給上一代碼加入更多的詞法作用域,且要加入實(shí)質(zhì)內(nèi)容才能起作用。
現(xiàn)在就能正常分別輸出數(shù)字1~5,每秒一次,每次一個(gè)。
總結(jié)
以上是生活随笔為你收集整理的JavaScript中的闭包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Ajax Extensions核心控件介
- 下一篇: gradle idea java ssm