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

資訊專欄INFORMATION COLUMN

談?wù)?setTimeout 這道經(jīng)典題目

Sleepy / 2279人閱讀

摘要:談?wù)勛约簩?duì)下面這道題目的理解問題這段代碼的輸出是三次,與預(yù)想的,,的輸出不符。此外,還可以使用下面這種方式這里可以使用閉包的知識(shí)進(jìn)行解釋有關(guān)閉包的內(nèi)容可以參見文末的參考鏈接,也可以用作用域輔助理解。

談?wù)勛约簩?duì)下面這道題目的理解

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

這段代碼的輸出是三次 4,與預(yù)想的 1,2,3 的輸出不符。以下解釋這一輸出的原因。

分析

我們可以將 setTimeout 的第一個(gè)參數(shù) timer() 多帶帶寫出來,變成如下代碼:

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

然后我們將循環(huán)展開,三次執(zhí)行過程的變化如下:

// 第一步: i = 1;
setTimeout( timer, 1 * 1000 );

// 第二步:i = 2;
setTimeout( timer, 2 * 1000 );

// 第三步 i = 3;
setTimeout( timer, 3 * 1000 );

注意,在循環(huán)過程中,timer() 函數(shù)并未變化,也沒有執(zhí)行( 計(jì)時(shí)器還未開始 )。

由于 JavaScript 中使用 var i = xxx 聲明的變量是函數(shù)級(jí)別( 而非塊級(jí) )的作用域,因而在 for 循環(huán)條件中聲明的 i 在 for 循環(huán)塊之外的最后一個(gè)函數(shù)體內(nèi)仍是可以訪問的,循環(huán)可以展開為:

var i = 4;
function timer() {
    console.log(i);
}
setTimeout( timer, 1 * 1000 );
setTimeout( timer, 2 * 1000 );
setTimeout( timer, 3 * 1000 );

因而當(dāng)計(jì)時(shí)器開始的 1s, 2s, 3s 后,timer 會(huì)分別執(zhí)行,此時(shí)會(huì)輸出三次 4。

解決方法

若要其每隔 1s 分別輸出 1, 2, 3,可以將 var i = 1 修改為 let i = 1,即:

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

注意,由于 let 屬于 ES6 的語法,請(qǐng)注意測(cè)試使用的瀏覽器。

此時(shí),由于 let i = xxx 為塊級(jí)別作用域,因而這一情況下的循環(huán)展開結(jié)果為:

{
    let i = 1;
    setTimeout( timer, 1 * 1000 );
}
{
    let i = 2;
    setTimeout( timer, 2 * 1000 );
}
{
    let i = 3;
    setTimeout( timer, 3 * 1000 );
}

注意:這里的 {} 僅用來強(qiáng)調(diào)塊級(jí)別作用域。

此時(shí)便可以得到我們想要的輸出結(jié)果了。

此外,還可以使用下面這種方式:

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

這里可以使用閉包的知識(shí)進(jìn)行解釋( 有關(guān)閉包的內(nèi)容可以參見文末的參考鏈接 ),也可以用作用域輔助理解。

由于 var i = xxx 是函數(shù)級(jí)別作用域,這里通過一個(gè)立即函數(shù)將變量 i 傳入其中,使其包含在這一函數(shù)的作用域中。而在每次循環(huán)中,此立即函數(shù)都會(huì)將傳入的 i 值保存下來,因而其循環(huán)展開結(jié)果為:

(function(){
    var count = 1;
    setTimeout( function timer() {
        console.log(count);
    }, count * 1000 );
})()
(function(){
    var count = 2;
    setTimeout( function timer() {
        console.log(count);
    }, count * 1000 );
})()
(function(){
    var count = 3;
    setTimeout( function timer() {
        console.log(count);
    }, count * 1000 );
})()

自然也會(huì)得到我們想要的輸出結(jié)果。

擴(kuò)展 - 塊級(jí)作用域和函數(shù)級(jí)作用域

可以用以下代碼進(jìn)行解釋:

{
    let i = 2;
    // 輸出 2
    console.log(i);
}
// 報(bào)錯(cuò):Uncaught ReferenceError: i is not defined
console.log(i);
function test(){
    // 由于變量提升,輸出 undefined
    console.log(a);
    {
        var a = 1;
    }
    // 輸出 1
    console.log(a);
}
// 按照函數(shù)內(nèi)的注釋輸出
test();
// 報(bào)錯(cuò):Uncaught ReferenceError: a is not defined
console.log(a);

注:const 聲明的常量與 let 相同,也為塊級(jí)作用域。

參考

for 循環(huán)中的...問題,為什么改 var 為 let 就可以解決? - segmentfault

ES6之let(理解閉包)和const命令 - 博客園

「每日一題」JS 中的閉包是什么? - 知乎專欄

前端基礎(chǔ)進(jìn)階(四):詳細(xì)圖解作用域鏈與閉包 - 簡(jiǎn)書

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81514.html

相關(guān)文章

  • JavaScript系列——JavaScript同步、異步、回調(diào)執(zhí)行順序之經(jīng)典閉包setTimeou

    摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問題,接著我就舉一個(gè)包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個(gè),第二個(gè)是一個(gè)回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來不順) 用公式表達(dá)就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來對(duì)付面試的...

    lewif 評(píng)論0 收藏0
  • JavaScript系列——JavaScript同步、異步、回調(diào)執(zhí)行順序之經(jīng)典閉包setTimeou

    摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問題,接著我就舉一個(gè)包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個(gè),第二個(gè)是一個(gè)回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來不順) 用公式表達(dá)就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來對(duì)付面試的...

    rockswang 評(píng)論0 收藏0
  • 前端er,你真的會(huì)用 async 嗎?

    摘要:異步函數(shù)是值通過事件循環(huán)異步執(zhí)行的函數(shù),它會(huì)通過一個(gè)隱式的返回其結(jié)果。 async 異步函數(shù) 不完全使用攻略 前言 現(xiàn)在已經(jīng)到 8012 年的尾聲了,前端各方面的技術(shù)發(fā)展也層出不窮,VueConf TO 2018 大會(huì) 也發(fā)布了 Vue 3.0的計(jì)劃。而在我們(我)的日常中也經(jīng)常用 Vue 來編寫一些項(xiàng)目。那么,就少不了 ES6 的登場(chǎng)了。那么話說回來,你真的會(huì)用 ES6 的 asyn...

    Jaden 評(píng)論0 收藏0
  • 4道經(jīng)典指針筆試題講解 ~

    摘要:結(jié)尾有關(guān)這四道經(jīng)典的指針筆試題講解就到此結(jié)束了,如果覺得文章對(duì)自己有所幫助,歡迎大家多多點(diǎn)贊收藏 ?前言 : 今天博主來講解4道經(jīng)典的指針筆試題,很多朋友沒有深刻理...

    tianren124 評(píng)論0 收藏0

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<