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

資訊專欄INFORMATION COLUMN

從閉包引出來的一系列問題

TigerChain / 3060人閱讀

摘要:從閉包引出來的一系列問題不起眼的開始很明顯,由于異步的作用。追問如果變成該怎樣處理首先可以使用閉包來解決這個問題利用立即執行函數,來解決閉包造成的問題。

從閉包引出來的一系列問題 1. 不起眼的開始
for(var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i)
    }, 1000)
}
console.log(new Date, i)

很明顯,由于異步的作用。到最后輸出的結果為6個5

如果用箭頭表示前后兩次輸出有1s的間隔,用,代表前后一起輸出,那么輸出結果是5->5,5,5,5,5

這個也很容易的就可以進行解釋,先執行console.log(),再進行setTimeout()的異步操作。

追問1:如果變成 5 -> 0,1,2,3,4 該怎樣處理?

首先可以使用閉包來解決這個問題:

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

利用立即執行函數,來解決閉包造成的問題。

此外還可以使用setTimeout的第三個參數 文檔:

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

可能會有很多同學采用ES6的方式來避免:

for(let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i)
    }, 1000)
}
console.log(new Date, i)

但是此時并不能正確輸出我們想要的結果,因為let聲明的 i 產生了塊級作用域,導致 for 循環外面的輸出不能獲取的 i ,所以此時會報錯 i is not defined

追問2:如果把輸出變為 0->1->2->3->4->5 呢?

其中一種比較容易想到的方法:

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

setTimeout(function() {
    console.log(new Date, i)
}, 1000*i)

但是js中定時器的觸發時機是不確定的,每次循環都會產生一個異步操作之后,會有一個輸出,那么完全可以使用Promise來解決這個問題。

const tasks = []
for(var i = 0; i < 5; i++) {
    (function(j){
        tasks.push(new Promise((resolve) => {
            setTimeout(() => {
                console.log(new Date, j)
                resolve()
            }, j*1000)
        }))
    })(i)
}

Promise.all(tasks).then( () => {
    setTimeout( () => {
        console.log(new Date, i)
    }, 1000)
})

將上面代碼處理一下:

const tasks = []
const output = function(i) {
    new Promise( (resolve) => {
        setTimeout( () => {
            console.log(new Date, i)
            resolve()
        }, 1000*i)
    })
}

for(var i = 0;i < 5; i++) {
    tasks.push(output(i))
}

// 全部Promise執行完畢,執行最后一個輸出i
Promise.all(tasks).then( () => {
    setTimeout( () => {
        console.log(new Date, i)
    }, 1000)
})
追問3:使用 async / await 怎么實現
// 模擬sleep
const sleep = (time) => new Promise((resolve) => {
    setTimeout(resolve, time);
});

(async () => {  // 聲明即執行的 async 函數表達式
    for (var i = 0; i < 5; i++) {
        if (i > 0) {
            await sleep(1000);
        }
        console.log(new Date, i);
    }

    await sleep(1000);
    console.log(new Date, i);
})();

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97099.html

相關文章

  • 夯實基礎-作用域與閉包

    摘要:作用域分類作用域共有兩種主要的工作模型。換句話說,作用域鏈是基于調用棧的,而不是代碼中的作用域嵌套。詞法作用域詞法作用域中,又可分為全局作用域,函數作用域和塊級作用域。 一篇鞏固基礎的文章,也可能是一系列的文章,梳理知識的遺漏點,同時也探究很多理所當然的事情背后的原理。 為什么探究基礎?因為你不去面試你就不知道基礎有多重要,或者是說當你的工作經歷沒有亮點的時候,基礎就是檢驗你好壞的一項...

    daydream 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...

    rottengeek 評論0 收藏0
  • 【譯】閉包并不神秘

    摘要:下面我們就初步嘗試一下閉包現在來看一下發生了什么。于是,這種結構就被稱作閉包。這就是閉包強大的地方。例如,如果我們可以在我們的計數器里面加一個名字我們可以往閉包里傳一個參數可以看出來,在實現過程中不僅能記住局部變量,也記住了傳進來的變量。 計數器 首先,從一個計數器開始。 var counter = 0; function increment() { counter = cou...

    sevi_stuo 評論0 收藏0
  • javascript系列--javascript擎執行的過程的理解--語法分析和預編譯階段

    摘要:所以覺得把這個執行的詳細過程整理一下,幫助更好的理解。類似的語法報錯的如下圖所示三預編譯階段代碼塊通過語法分析階段之后,語法都正確的下回進入預編譯階段。另開出新文章詳細分析,主要介紹執行階段中的同步任務執行和異步任務執行機制事件循環。 一、概述 js是一種非常靈活的語言,理解js引擎的執行過程對于我們學習js是非常有必要的。看了很多這方便文章,大多數是講的是事件循環(event loo...

    malakashi 評論0 收藏0
  • JS專題之去抖函數

    摘要:如果本次定時器沒有被清除,時間到后就會自然執行事件處理函數。綁定去抖后的事件回調函數綁定回調函數的屬性方法,點擊頁面,重置去抖效果異步請求清空上一次事件觸發的定時器重置為從而下一次事件觸發就能立即執行。 一、前言 為什么會有去抖和節流這類工具函數? 在用戶和前端頁面的交互過程中,很多操作的觸發頻率非常高,比如鼠標移動 mousemove 事件, 滾動條滑動 scroll 事件, 輸...

    ivydom 評論0 收藏0

發表評論

0條評論

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