閉包

每一個(gè)函數(shù)都有其所處的作用域戳杀,如果函數(shù)是在作用域之外(對(duì)于函數(shù)而言步做,作用域只跟聲明時(shí)所處的位置有關(guān),跟調(diào)用處無(wú)關(guān))執(zhí)行時(shí)酣胀,此時(shí)函數(shù)如果能夠記住并訪問(wèn)得到自己所在的作用域的話刁赦,那么此時(shí)便形成了一個(gè)閉包。

看一個(gè)簡(jiǎn)單例子:

function foo(){
  var a = 2
  function bar(){console.log(a)}//bar函數(shù)所處的作用域即foo函數(shù)內(nèi)部塊中
  return bar
}
var baz = foo()
baz()//2

通過(guò)上面的例子結(jié)合自己實(shí)際經(jīng)驗(yàn)闻镶,你會(huì)發(fā)現(xiàn)閉包真的就是無(wú)處不在甚脉。下面分析一下:當(dāng)我們通過(guò)函數(shù)變量baz調(diào)用函數(shù)的時(shí)候,此時(shí)調(diào)用的便是內(nèi)存中的bar函數(shù)铆农。需要記住的是牺氨,盡管是不同的名字,但是對(duì)于淺拷貝來(lái)說(shuō),他們實(shí)際上引用的都是同一塊內(nèi)存中的數(shù)據(jù)猴凹,所以說(shuō)夷狰,這里的bar()和baz()是一樣的結(jié)果,問(wèn)題是閉包會(huì)產(chǎn)生這樣一種效果:阻止垃圾回收機(jī)制回收f(shuō)oo函數(shù)內(nèi)部塊中的某些數(shù)據(jù)郊霎,比如說(shuō)我們這里要用上的a以及bar函數(shù)本身沼头。對(duì)于函數(shù)而言,他的作用域和調(diào)用位置無(wú)關(guān)歹篓,所以說(shuō)關(guān)于閉包的核心點(diǎn)就是:對(duì)所需要用的資源的延遲回收瘫证。

下面來(lái)兩個(gè)復(fù)習(xí)作用域的例子:

var a = 3
function foo(){
  var a = 2
  function bar(){console.log(a)}
  return bar
}
var baz = foo()
baz()//2

再看看下面這個(gè)例子

function handle(fun){
    var test = 1
    var num = fun()
    return num+1
}
function dowork(){
    var test = 6
    var nm = handle(function ques(){console.log(test);return 1})//6
    console.log(nm)//2
    //var can = ques//ReferenceError,ques is not defined
}
dowork()
//輸出結(jié)果=>6 2

討論一下ques函數(shù)所處的作用域揉阎,猜測(cè)一:dowork塊庄撮;猜測(cè)二:handle塊。根據(jù)運(yùn)行結(jié)果很容易得知毙籽,肯定不是handle塊洞斯。那么是不是dowork塊?根據(jù)6這個(gè)輸出結(jié)果來(lái)看坑赡,我們可以得知可能是dowork塊烙如,但是既讓如此為什么在dowork塊里面不能訪問(wèn)得到ques函數(shù)呢?這又使得我們懷疑是否是dowork塊毅否。經(jīng)過(guò)思考發(fā)現(xiàn)亚铁,ques函數(shù)的作用域的確是dowork塊,那么為什么不能再dowork內(nèi)部訪問(wèn)ques呢螟加?答案是這樣的徘溢,先舉個(gè)例子:

var fun = function bar(){console.log(1)}
bar()//ReferenceError

就是上面的這種情況,一樣的道理捆探,但我們將一個(gè)函數(shù)聲明的代碼作為右值賦值的時(shí)候然爆,那么函數(shù)聲明中的那個(gè)名字會(huì)被編譯器給忽略。

1.循環(huán)與閉包

先看一個(gè)經(jīng)典例子:

for(var i = 0; i < 10; i++){
  setTimeout(function(){console.log(i)}, i*1000)
}

分析:運(yùn)行的結(jié)果是——連續(xù)輸出了10個(gè)10黍图,每間隔1s輸出一次曾雕。但是,我們期望的可不是這樣的助被,我們希望能夠輸出0123456789剖张,那么問(wèn)題來(lái)了,為什么會(huì)導(dǎo)致這個(gè)問(wèn)題呢揩环?答案就是修械,setTimeout函數(shù)的特殊性,延時(shí)函數(shù)里面的回調(diào)函數(shù)會(huì)在循環(huán)結(jié)束時(shí)才執(zhí)行检盼。那么你設(shè)置的延時(shí)時(shí)間是0而不是1s肯污,所有的回調(diào)函數(shù)仍舊是在循環(huán)結(jié)束時(shí)才會(huì)執(zhí)行。而我們這里的回調(diào)函數(shù)的操作就是輸出變量i,由于是循環(huán)結(jié)束才會(huì)開始執(zhí)行回調(diào)函數(shù)蹦渣,所以他們都輸出了變量最后的那個(gè)值10哄芜。
要解決這個(gè)問(wèn)題有好多辦法,這里就介紹最簡(jiǎn)單的那個(gè)柬唯,利用let關(guān)鍵字:

for(let i = 0; i < 10; i++){
  setTimeout(function(){console.log(i)}, i*1000)
}

當(dāng)for與let結(jié)合時(shí)认臊,let聲明的變量在每次循環(huán)都會(huì)被再次聲明。第n次聲明時(shí)所賦的值由第n-1次結(jié)束時(shí)的值來(lái)決定锄奢。

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末失晴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拘央,更是在濱河造成了極大的恐慌涂屁,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灰伟,死亡現(xiàn)場(chǎng)離奇詭異拆又,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)栏账,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門帖族,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人挡爵,你說(shuō)我怎么就攤上這事竖般。” “怎么了茶鹃?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵涣雕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我前计,道長(zhǎng)胞谭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任男杈,我火速辦了婚禮丈屹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伶棒。我一直安慰自己旺垒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布肤无。 她就那樣靜靜地躺著先蒋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宛渐。 梳的紋絲不亂的頭發(fā)上竞漾,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天眯搭,我揣著相機(jī)與錄音,去河邊找鬼业岁。 笑死鳞仙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笔时。 我是一名探鬼主播棍好,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼允耿!你這毒婦竟也來(lái)了借笙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤较锡,失蹤者是張志新(化名)和其女友劉穎业稼,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體念链,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盼忌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年积糯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掂墓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡看成,死狀恐怖君编,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情川慌,我是刑警寧澤吃嘿,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站梦重,受9級(jí)特大地震影響兑燥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琴拧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一降瞳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚓胸,春花似錦挣饥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至锹安,卻和暖如春短荐,著一層夾襖步出監(jiān)牢的瞬間倚舀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工忍宋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞄桨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓讶踪,卻偏偏與公主長(zhǎng)得像芯侥,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乳讥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持柱查,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠云石,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 5,610評(píng)論 16 88
  • You don't KnowJS 引語(yǔ):你不懂的JS這本書?github上已經(jīng)有了7w的star最近也是張野大大給...
    Sleet閱讀 582評(píng)論 0 0
  • 特別說(shuō)明唉工,為便于查閱,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 486評(píng)論 0 0
  • 函數(shù)只能在其所在的作用域內(nèi)調(diào)用嗎汹忠?怎樣在一個(gè)函數(shù)所在的作用域之外調(diào)用該函數(shù)淋硝?比如下面代碼,函數(shù)bar定義在函數(shù)fo...
    閆浩奇閱讀 497評(píng)論 0 4
  • 1.對(duì)象是什么 對(duì)象就是若干屬性的集合宽菜。 在JS中一切引用類型都是對(duì)象:數(shù)組是對(duì)象谣膳,函數(shù)是對(duì)象,對(duì)象還是對(duì)象铅乡。對(duì)象...
    liushaung閱讀 1,209評(píng)論 0 2