国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

循環(huán)和閉包

Cc_2011 / 1239人閱讀

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

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

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

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

這是為什么?

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

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

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

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

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

他需要自己的變量,用來在每個迭代中存儲i的值:

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

ok,他運行如我們所愿了!

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

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

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

使用let解決

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

    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)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/94919.html

相關(guān)文章

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

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

    teren 評論0 收藏0
  • 前端小知識--從Javascript閉包看let

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

    Kross 評論0 收藏0
  • JavaScript中的閉包

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

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

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

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

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

    曹金海 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<