成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

循環(huán)和閉包

Cc_2011 / 1242人閱讀

摘要:所以所有函數(shù)共享一個(gè)的引用時(shí),循環(huán)結(jié)構(gòu)讓我們誤認(rèn)為背后還有更復(fù)雜的機(jī)制在器作用,但實(shí)際上啥都木有,如果將延遲函數(shù)的回調(diào)重復(fù)定義五次,完全不使用循環(huán),那他同這段代碼是完全等價(jià)的。

想要說(shuō)明閉包,for循環(huán)是最常見的例子:

for(var i=1;i<=5;i++)
{
    setTimeout(function timer(){
        console.log(i);
    },i*1000);
}

以我們所想,我們可能認(rèn)為他會(huì)輸出1~5,每秒一次,每次一個(gè)。
但實(shí)際上,這段代碼在運(yùn)行時(shí)會(huì)以每秒一次的頻率輸出五次6。

這是為什么?

原因是延遲函數(shù)會(huì)在循環(huán)結(jié)束時(shí)才執(zhí)行,事實(shí)上,當(dāng)定時(shí)器運(yùn)行時(shí)即使每個(gè)迭代中執(zhí)行的是setTimeout(...,0),所有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會(huì)執(zhí)行,因此會(huì)每次輸出一個(gè)6出來(lái)。

根據(jù)作用域的原理,實(shí)際情況:盡管循環(huán)中的五個(gè)函數(shù)是在各個(gè)迭代中分別定義的,但是他們都被封閉在一個(gè)共享的全局作用域中,因此實(shí)際上只有一個(gè)i。
所以所有函數(shù)共享一個(gè)i的引用時(shí),循環(huán)結(jié)構(gòu)讓我們誤認(rèn)為背后還有更復(fù)雜的機(jī)制在器作用,但實(shí)際上啥都木有,如果將延遲函數(shù)的回調(diào)重復(fù)定義五次,完全不使用循環(huán),那他同這段代碼是完全等價(jià)的。

解決方法如下:
我們先試一下:

    for(var i=1;i<5;i++){
        (function(){
            setTimeout(function timer(){
                console.log(i);
            },i*1000);
        })();
    }

看似可以,但實(shí)際也沒用,雖然這樣寫我們有更多詞法作用域了,的確每個(gè)延遲函數(shù)都會(huì)將IIFE在每次迭代中創(chuàng)建的作用域封閉起來(lái)。
如果作用域是空的,那么僅僅將他們進(jìn)行封閉是不夠的。仔細(xì)看一下,我們的IIFE只是一個(gè)什么都沒有的空作用域,所以需要包含一點(diǎn)實(shí)際內(nèi)容為我們所用。

他需要自己的變量,用來(lái)在每個(gè)迭代中存儲(chǔ)i的值:

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

ok,他運(yùn)行如我們所愿了!

可以進(jìn)行改進(jìn):

    for(var i=1;i<=5;i++)
    {
        (function{
            setTimeout(function timer(){
                console.log(j);
            },j*1000);
        })(i);    //i可以改動(dòng),只要你喜歡
    }

在迭代內(nèi)使用IIFE會(huì)為每個(gè)迭代都生成一個(gè)新的作用域,使得延遲函數(shù)的回調(diào)可以將新的作用域封閉在每個(gè)迭代內(nèi)部,每個(gè)迭代中都會(huì)包含一個(gè)具有正確值的變量供我們?cè)L問(wèn)。

使用let解決

for循環(huán)的let聲明還會(huì)有一個(gè)特殊行為,這個(gè)行為之處變量在循環(huán)過(guò)程中不知被聲明一次,每次迭代都會(huì)聲明,隨后的每個(gè)迭代都會(huì)使用上一個(gè)迭代結(jié)束時(shí)的值來(lái)初始化這個(gè)變量。

    for(var i=1;i<=5;i++)
    {
        let j=i;  //閉包
        setTimeout(function timer(){
            console.log(j);
        },j*1000);
    }
    
    下面是進(jìn)化版
    
    for(let i;i<=5;i++)
    {
        setTimeout(function timer(){
            console.log(i);
        },i*1000);
    }

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94919.html

相關(guān)文章

  • [Javascript實(shí)驗(yàn)課]循環(huán)中的閉包

    摘要:執(zhí)行出來(lái)的結(jié)果是這樣的實(shí)驗(yàn)發(fā)現(xiàn),無(wú)論如何都在最后執(zhí)行,這證實(shí)了我們之前遇到的問(wèn)題,因?yàn)樵谘h(huán)結(jié)束才執(zhí)行,所以回調(diào)函數(shù)調(diào)用的取值必然是循環(huán)的最后一次。 前言 https://developer.mozilla.org/zh-CN/docs/JavaScript/Guide/Closures MDN上描述閉包的章節(jié)闡述了一個(gè)由于閉包產(chǎn)生的常見錯(cuò)誤,代碼片段是這樣的 for (var i...

    teren 評(píng)論0 收藏0
  • 前端小知識(shí)--從Javascript閉包看let

    摘要:閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。立即執(zhí)行函數(shù)立即執(zhí)行函數(shù),顧名思義,立即會(huì)執(zhí)行的函數(shù),即當(dāng)讀取到該函數(shù),會(huì)立即執(zhí)行。特性使用語(yǔ)句聲明一個(gè)變量,該變量的范圍限于聲明它的塊中。使用聲明的變量,在聲明前無(wú)法使用,否則將會(huì)導(dǎo)致錯(cuò)誤。 let和閉包 之前一直模模糊糊記得,let解決了某個(gè)閉包問(wèn)題,想用時(shí)又不敢肯定,今天終于遇到這個(gè)問(wèn)題了,那我們就一起來(lái)分析一下,什么是let,let有...

    Kross 評(píng)論0 收藏0
  • JavaScript中的閉包

    摘要:權(quán)威指南第版中閉包的定義函數(shù)對(duì)象可以通過(guò)作用域鏈相互關(guān)聯(lián)起來(lái),函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),這種特性在計(jì)算機(jī)科學(xué)文獻(xiàn)中成為閉包。循環(huán)中的閉包使用閉包時(shí)一種常見的錯(cuò)誤情況是循環(huán)中的閉包,很多初學(xué)者都遇到了這個(gè)問(wèn)題。 閉包簡(jiǎn)介 閉包是JavaScript的重要特性,那么什么是閉包? 《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》中閉包的定義: 閉包就是指有權(quán)訪問(wèn)另一個(gè)函數(shù)中的變...

    Donne 評(píng)論0 收藏0
  • JS 基礎(chǔ)篇--閉包引用

    摘要:因?yàn)闆]有塊級(jí)作用域,只有函數(shù)作用域,所以閉包的使用與函數(shù)是緊密相關(guān)的。模擬私有變量這里返回兩個(gè)閉包函數(shù)和。閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。 簡(jiǎn)介 Javascript 中一個(gè)最重要的特性就是閉包的使用。因?yàn)殚]包的使用,當(dāng)前作用域總可以訪問(wèn)外部的作用域。因?yàn)镴avascript 沒有塊級(jí)作用域,只有函數(shù)作用域,所以閉包的使用與函數(shù)是緊密相關(guān)的。 各種專業(yè)文獻(xiàn)上的閉包(clos...

    EdwardUp 評(píng)論0 收藏0
  • 深入理解JavaScript(二):由一道題來(lái)思考閉包

    摘要:中所有的事件綁定都是異步編程當(dāng)前這件事件沒有徹底完成,不再等待,繼續(xù)執(zhí)行下面的任務(wù)當(dāng)綁定事件后,不需要等待執(zhí)行,繼續(xù)執(zhí)行下一個(gè)循環(huán)任務(wù),所以當(dāng)我們點(diǎn)擊執(zhí)行方法的時(shí)候,循環(huán)早已結(jié)束即是最后。 概念 閉包就是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù) 點(diǎn)擊li標(biāo)簽彈出對(duì)應(yīng)數(shù)字 0 1...

    曹金海 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<