亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

一個js面試題

一個js面試題

明月笑刀無情 2018-08-02 21:35:36
for (var i = 0; i < 5; i++) {     setTimeout(function() {                 console.log(new Date, i);     }, 1000); }console.log(new Date, i);能想到答案是5,5,5,5,5。感覺應該是因為異步代碼。但根據作者的話“ 只要你對 JS 中同步和異步代碼的區別、變量作用域、閉包等概念有正確的理解,就知道正確答案”。不知道這里怎么和閉包有關系。還有個就是輸出的結果為什么最后4個5是同時輸出的。2017-03-18T00:43:45.873Z 52017-03-18T00:43:46.866Z 52017-03-18T00:43:46.868Z 52017-03-18T00:43:46.868Z 52017-03-18T00:43:46.868Z 52017-03-18T00:43:46.868Z 5
查看完整描述

2 回答

?
蝴蝶刀刀

TA貢獻1801條經驗 獲得超8個贊

閉包的產生就是局部作用域中有對外部作用域變量的引用,原代碼指向的是一個全局變量所以毫無意義

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

這樣就很好理解了,let聲明的變量具有塊級作用域,只有在代碼塊中能使用,代碼塊中掛起的異步函數能訪問到i(塊級作用域中的i)
異步函數中有對外部變量i的引用從而產生閉包
而外部使用變量會因為沒有聲明而報錯
一開始的代碼輸出5個5是因為執行異步代碼 setTimeout(function() { console.log(new Date, i); }, 100);中的console.log(new Date, i);時for循環已經完畢了,i已經是5了,注意setTimeout(...)是同步的,其中的代碼塊是異步的
或者這樣

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

這里相當于保存了i的快照版本作為參數傳入
至于為什么是同步輸出的(其實是依次輸出的),for循環執行setTimeout是同步的,又沒阻塞代碼存在每次循環的時間間隔小到可以忽略不計,執行異步代碼也沒有其他異步代碼與阻塞代碼的干擾,所以執行的時候感覺是一瞬間一起出現的


查看完整回答
反對 回復 2018-08-05
?
互換的青春

TA貢獻1797條經驗 獲得超6個贊

setTimeout是延時執行,但是他其實是不準確的。后面的毫秒數代表著他在多少毫秒后會進入執行隊列里面。如果你前面有一個占用了非常多時間的運算。setTimeout就會延時特別久。他只在當前隊列執行完之后,才嘗試執行。

for (var i = 0; i < 5; i++) {   
    //延遲執行
    setTimeout(function() {        
        console.log(new Date, i);
    }, 1000);
}    
console.log(new Date, i);
alert("我們用alert掛起一下程序,你等待兩三秒再確定");//執行到這里,這個隊列才算是執行完了。然后才會嘗試執行你的settimeout延時的程序,看看是不是可以調用了。不信你看看時間

https://img1.sycdn.imooc.com//5b67138c0001eb1e05460575.jpg


查看完整回答
反對 回復 2018-08-05
  • 2 回答
  • 0 關注
  • 983 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號