摘要:而閉包的神奇之處在于可以阻止這件事情的發(fā)生。依然持有對(duì)該作用域的引用,而這個(gè)引用就叫做閉包。當(dāng)然,無(wú)論使用何種方式對(duì)函數(shù)類型的值進(jìn)行傳遞,當(dāng)函數(shù)在別處被調(diào)用時(shí)都可以觀察到閉包。
下面我們來(lái)看一段代碼,清晰地展示了閉包:
function foo(){ var a=2; function bar(){ console.log(a); } return bar; } var baz=foo(); baz() //2,這就是閉包
函數(shù)bar()的詞法作用域能夠訪問(wèn)foo()的內(nèi)部作用域,然后我們將bar()函數(shù)本身當(dāng)作一個(gè)值類型進(jìn)行傳遞。在這個(gè)例子中,我們將bar
所引用的函數(shù)對(duì)象本身當(dāng)作返回值。
在foo()執(zhí)行后,其返回值(也就是內(nèi)部的bar()函數(shù))賦值給變量baz并調(diào)用baz(),實(shí)際上只是通過(guò)不同的標(biāo)識(shí)符引用調(diào)用了內(nèi)部的函數(shù)
baz().雖然baz()被正常執(zhí)行,但是它是在自己定義的詞法作用域以外的地方執(zhí)行。
由于存在引擎垃圾回收器來(lái)釋放不再使用的內(nèi)存空間,由于看上去foo()的內(nèi)容不會(huì)再被引用,所以很自然地會(huì)考慮對(duì)其進(jìn)行回收。
而閉包的神奇之處在于可以阻止這件事情的發(fā)生。所以內(nèi)部作用域依然存在,而且就是baz()本身在使用。
bar()依然持有對(duì)該作用域(foo())的引用,而這個(gè)引用就叫做閉包。
當(dāng)然,無(wú)論使用何種方式對(duì)函數(shù)類型的值進(jìn)行傳遞,當(dāng)函數(shù)在別處被調(diào)用時(shí)都可以觀察到閉包。
function foo(){ var a=2; function baz(){ console.log(a);//2 } bar(baz); } function bar(fn){ fn(); //這就是閉包 }
把內(nèi)部函數(shù)baz傳遞給bar,當(dāng)調(diào)用這個(gè)內(nèi)部函數(shù)是(現(xiàn)在叫做fn),它涵蓋的foo()內(nèi)部作用域的閉包就可以觀察到了,因?yàn)樗軌蛟L問(wèn)a。
傳遞的函數(shù)當(dāng)然也可以是間接的:
var fn; function foo(){ var a=2; function baz(){ console.log(a); } fn=baz; } function bar(){ fn(); } foo(); bar(); //2
所以無(wú)論通過(guò)何種手段將內(nèi)部函數(shù)傳遞到所在的詞法作用域以外,它都會(huì)持有對(duì)原始定義作用域的引用,無(wú)論在何處執(zhí)行這個(gè)函數(shù)都會(huì)使用閉包。
上面是為了可以解釋如何使用閉包而故意在結(jié)構(gòu)上加了些許修飾,下面我們來(lái)看日常使用到的閉包。
function wait(message){ setTimeout(function timer(){ console.log(message); },1000); } wait("Hello,closure");
將一個(gè)內(nèi)部函數(shù)(timer)傳遞給setTimeout(...).timer具有涵蓋wait()作用域的閉包,因此還保有對(duì)變量message的引用。
在引擎內(nèi)部,內(nèi)置的工具函數(shù)setTimeout()持有對(duì)一個(gè)參數(shù)的引用,這個(gè)參數(shù)也許叫做fn或者fnc,或者其他類似的名字。引擎會(huì)調(diào)用這個(gè)函數(shù),
在例子中就是內(nèi)部的timer函數(shù),而詞法作用域在這個(gè)過(guò)程保持完整。
再來(lái)看一個(gè)jq的:
function setupBot(name,selector){ $(selector).click(function activator(){ console.log("Activating:"+name); }); } setupBot("Closure Bot1","#bot_1"); setupBot("Closure Bot2","#bot_2");
本質(zhì)上無(wú)論何時(shí)何地,如果將(訪問(wèn)他們各自詞法作用域的)函數(shù)當(dāng)作第一級(jí)的值類型并導(dǎo)出傳遞,你就會(huì)看到閉包在這些函數(shù)中的應(yīng)用。在定時(shí)器、
事件監(jiān)聽(tīng)器、Ajax請(qǐng)求、跨窗口通信,Web Workers或者任何其他異步(或者同步)任務(wù)中,只要使用了回調(diào)函數(shù),實(shí)際上就是在使用閉包!
(參考《你不知道的JavaSctipt上卷》)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94924.html
摘要:大名鼎鼎的閉包面試必問(wèn)。閉包的作用是什么??吹介]包在哪了嗎閉包到底是什么五年前,我也被這個(gè)問(wèn)題困擾,于是去搜了并總結(jié)下來(lái)。關(guān)于閉包的謠言閉包會(huì)造成內(nèi)存泄露錯(cuò)。閉包里面的變量明明就是我們需要的變量,憑什么說(shuō)是內(nèi)存泄露這個(gè)謠言是如何來(lái)的因?yàn)椤? 本文為饑人谷講師方方原創(chuàng)文章,首發(fā)于 前端學(xué)習(xí)指南。 大名鼎鼎的閉包!面試必問(wèn)。請(qǐng)用自己的話簡(jiǎn)述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:完美的閉包,對(duì),閉包就這么簡(jiǎn)單。這僅僅是閉包的一部分,閉包利用函數(shù)作用域達(dá)到了訪問(wèn)外層變量的目的。此時(shí)一個(gè)完整的閉包實(shí)現(xiàn)了,的垃圾回收機(jī)制由于閉包的存在無(wú)法銷毀變量。 1.閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù)。 上面這段話來(lái)自 javascript 高級(jí)程序設(shè)計(jì) 第三版 P178 。作者說(shuō)閉包是一個(gè)函數(shù),它有訪問(wèn)另一個(gè)函數(shù)作用域中的變量的能力。 2.函數(shù)訪問(wèn)它被創(chuàng)建時(shí)所處的...
摘要:第二梯隊(duì)理解有了第一梯隊(duì)的認(rèn)識(shí),我們慢慢修正大腦中對(duì)閉包的認(rèn)識(shí)。理解這句話就可以很好的與閉包這兩個(gè)字關(guān)聯(lián)起來(lái)理解閉包這個(gè)概念了。總結(jié)第二梯隊(duì)理解閉包是一個(gè)有特定功能的函數(shù)。第四梯隊(duì)理解閉包通過(guò)訪問(wèn)外部變量,一個(gè)閉包可以維持這些變量。 閉包 閉包的概念困惑了我很久,記得當(dāng)時(shí)我面試的時(shí)候最后一面有一個(gè)問(wèn)題就是問(wèn)題關(guān)于閉包的問(wèn)題,然而到現(xiàn)在已經(jīng)完全不記得當(dāng)時(shí)的題目是啥了,但仍然能夠回憶起當(dāng)時(shí)...
摘要:到底什么是閉包這個(gè)問(wèn)題在面試是時(shí)候經(jīng)常都會(huì)被問(wèn),很多小白一聽(tīng)就懵逼了,不知道如何回答好。上面這么說(shuō)閉包是一種特殊的對(duì)象。閉包的注意事項(xiàng)通常,函數(shù)的作用域及其所有變量都會(huì)在函數(shù)執(zhí)行結(jié)束后被銷毀。從而使用閉包模塊化代碼,減少全局變量的污染。 閉包,有人說(shuō)它是一種設(shè)計(jì)理念,有人說(shuō)所有的函數(shù)都是閉包。到底什么是閉包?這個(gè)問(wèn)題在面試是時(shí)候經(jīng)常都會(huì)被問(wèn),很多小白一聽(tīng)就懵逼了,不知道如何回答好。這個(gè)...
閱讀 1814·2023-04-26 02:14
閱讀 3739·2021-11-23 09:51
閱讀 1391·2021-10-13 09:39
閱讀 3981·2021-09-24 10:36
閱讀 3020·2021-09-22 15:55
閱讀 3525·2019-08-30 12:57
閱讀 2045·2019-08-29 15:30
閱讀 1989·2019-08-29 13:19