摘要:概念當(dāng)函數(shù)可以記住并訪問(wèn)所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行。
概念
例子 問(wèn)題當(dāng)函數(shù)可以記住并訪問(wèn)所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行。
下面的代碼的運(yùn)行結(jié)果和代碼語(yǔ)意上表達(dá)的不相符,我們希望它能夠每隔一秒輸出一次,每次輸出對(duì)應(yīng)的數(shù)字,即第一秒后輸出1,第二秒后輸出2......
而這段代碼的運(yùn)行結(jié)果是,第一秒后輸出6,第二秒后輸出6......
請(qǐng)解釋原因并且提出修改方案。(包含要點(diǎn),函數(shù)作用域,塊作用域,閉包,let)
for (var i = 1; i <= 5; i++) { setTimeout(function timer() { console.log(i); }, i*1000); }答案 解釋原因
var i,實(shí)際上聲明了一個(gè)全局變量
延遲函數(shù)timer必然是在循環(huán)結(jié)束后才開(kāi)始執(zhí)行,循環(huán)結(jié)束后,i=6
循環(huán)中確實(shí)定義了多個(gè)延遲函數(shù)timer,延遲函數(shù)在setTimeout的內(nèi)部被回調(diào),根據(jù)閉包概念,timer在其聲明之外的地方被調(diào)用,timer能夠記住并訪問(wèn)其聲明位置的詞法作用域,存在閉包
實(shí)際上timer所記住的詞法作用域就是全局作用域,所以引用輸出的i都是6
修改方案只要能保證每次循環(huán)都能夠創(chuàng)建新的作用域,在新作用域中保存當(dāng)前i的值即可
所以任何可以創(chuàng)建新作用域的方法都可以達(dá)到效果,具體可參考這里,通過(guò)分析這段代碼的進(jìn)化歷程,或許能夠加深您對(duì)JavaScript的作用域的理解
常見(jiàn)的做法有
利用具名立即執(zhí)行函數(shù),每次循環(huán)都創(chuàng)建新作用域
for (var i = 1; i <= 5; i++) { (function scope(j) { setTimeout(function timer() { console.log(j); }, i * 1000); })(i); }
利用es6 let創(chuàng)建塊作用域
for (var i = 1; i <= 5; i++) { { let j = i; setTimeout(function timer() { console.log(j); }, i * 1000); } }總結(jié)
根據(jù)閉包的概念,只要有回調(diào)就會(huì)有閉包......
記住這個(gè)例子,還怕被問(wèn)閉包?
最近寫(xiě)了三篇,參考書(shū)籍主要是《你不知道的JavaScript(上卷)》,看完這三篇可以說(shuō)就相當(dāng)于看了半本書(shū)了,^_^
前端框架層出不窮,不反對(duì)使用框架,但一定要有頭頭能駕馭的了它。試想,做前端的人那么多,如果冰河世紀(jì)來(lái)臨,存活下來(lái)的還是那些會(huì)寫(xiě)框架的人,那些只懂框架使用的人就危險(xiǎn)了
我快畢業(yè)了,但心里慌慌的,所以如果您剛?cè)腴T(mén),建議還是扎扎實(shí)實(shí)地學(xué)基礎(chǔ),其實(shí)JS基礎(chǔ)遠(yuǎn)比您想象的要復(fù)雜,千萬(wàn)別以為自己看了W3C School就覺(jué)得自己Ok了,反正我是要再努力下,爭(zhēng)取看得懂牛人的代碼哈
下篇見(jiàn)......
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/79370.html
摘要:能達(dá)到一個(gè)積木塊模塊的要求。接下來(lái)我們將改進(jìn)它。結(jié)尾到此,我們自己構(gòu)建了一個(gè)很實(shí)用的模塊化工具,項(xiàng)目的源碼在這里,喜歡的話,給個(gè)。 前言 希望編寫(xiě)程序能像玩積木一樣,首先規(guī)劃要產(chǎn)出怎樣的作品,然后在積木堆中挑選合適的積木塊,最后一組合就完工了。 于是JavaScript需要類似這樣模塊化,每個(gè)模塊都隱藏內(nèi)部細(xì)節(jié)并且對(duì)外暴露接口,再處理好模塊之間的依賴關(guān)系,就可以達(dá)到玩積木的效果了。 雖...
摘要:當(dāng)在中調(diào)用匿名函數(shù)時(shí),它們用的都是同一個(gè)閉包,而且在這個(gè)閉包中使用了和的當(dāng)前值的值為因?yàn)檠h(huán)已經(jīng)結(jié)束,的值為。最好將閉包當(dāng)作是一個(gè)函數(shù)的入口創(chuàng)建的,而局部變量是被添加進(jìn)這個(gè)閉包的。 閉包不是魔法 這篇文章使用一些簡(jiǎn)單的代碼例子來(lái)解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實(shí)只要理解了核心概念,閉包并不是那么的難于理解。但是,網(wǎng)上充斥了太多學(xué)術(shù)性的文章,對(duì)于...
摘要:也就是說(shuō),所有的函數(shù)和構(gòu)造函數(shù)都是由生成,包括本身。如果只考慮構(gòu)造函數(shù)和及其關(guān)聯(lián)的原型對(duì)象,在不解決懸念的情況下,圖形是這樣的可以看到,每一個(gè)構(gòu)造函數(shù)和它關(guān)聯(lián)的原型對(duì)象構(gòu)成一個(gè)環(huán),而且每一個(gè)構(gòu)造函數(shù)的屬性無(wú)所指。 前言 JavaScript 是我接觸到的第二門(mén)編程語(yǔ)言,第一門(mén)是 C 語(yǔ)言。然后才是 C++、Java 還有其它一些什么。所以我對(duì) JavaScript 是非常有感情的,畢...
摘要:那這條消息的延遲就是秒鐘。避免一個(gè)遲遲湊不滿,導(dǎo)致消息一直積壓在內(nèi)存里發(fā)送不出去的情況。個(gè)人公眾號(hào):石杉的架構(gòu)筆記(ID:shishan100)目錄1、背景引入:很多同學(xué)看不懂Kafka參數(shù)2、一段Kafka生產(chǎn)端的示例代碼3、內(nèi)存緩沖的大小4、多少數(shù)據(jù)打包為一個(gè)Batch合適?5、要是一個(gè)Batch遲遲無(wú)法湊滿咋辦?6、最大請(qǐng)求大小7、重試機(jī)制8、持久化機(jī)制 1、背景引入:很多同學(xué)看不懂k...
摘要:安裝此處先省略算了我還是分享一下吧嘿嘿鏈接提取碼至于安裝步驟選擇好安裝路徑直接就可以了了解功能模塊能點(diǎn)進(jìn)這篇文章的人就不用介紹是用來(lái)干什么的了幫助我們本地測(cè)試方式本地測(cè)試方式本地測(cè)試方式測(cè)試文件的上傳功能我以文件為例方 ...
閱讀 723·2021-10-09 09:41
閱讀 715·2019-08-30 15:53
閱讀 1143·2019-08-30 15:53
閱讀 1273·2019-08-30 11:01
閱讀 1639·2019-08-29 17:31
閱讀 1063·2019-08-29 14:05
閱讀 1787·2019-08-29 12:49
閱讀 471·2019-08-28 18:17