一道容易栽坑的有趣的面試題(關於js,定時器,閉包等)


1.首先下面代碼輸出什么?

1 for (var i = 0; i < 5; i++) {
2   console.log(i);
3 }

輸出:0 1 2 3 4

 

2.上面只是普通的輸出,沒有陷阱再看下面這個題(套路開始了)

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

輸出:5 5 5 5 5 

setTimeout 會延遲執行,那么執行到 console.log 的時候,其實 i 已經變成 5 了,因此會輸出5個5

 

3.上面的題超出我們的預想,我們肯定想得到的是0 1 2 3 4,那么問題來了 怎么才能輸出0 1 2 3 4呢

1 for (var i = 0; i < 5; i++) {
2   (function(i) {
3     setTimeout(function() {
4       console.log(i);
5     }, i * 1000);
6   })(i);
7 }

或者:

1 for(var i = 0; i < 5; i++) {
2     setTimeout(function(i) {
3         return function() {
4             console.log(i);
5         };
6     }(i), i * 1000);
7 }

輸出:0 1 2 3 4

加上閉包,就能解決這個問題

 

4.如第一個假設刪除了function(i)中的i呢,怎么辦?

1 for (var i = 0; i < 5; i++) {
2   (function() {
3     setTimeout(function() {
4       console.log(i);
5     }, i * 1000);
6   })(i);
7 }

輸出:5 5 5 5 5 

內部其實沒有對 i 保持引用,其實會變成輸出 5個5

 

5.再更改一下

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

輸出:0 1 2 3 4 (立刻輸出,沒有時間間隔)

給 setTimeout 傳遞了一個立即執行函數。setTimeout 可以接受函數或者字符串作為參數,那么這里立即執行函數是個啥呢,應該是個 undefined ,也就是說等價於:

setTimeout(undefined, ...);

而立即執行函數會立即執行,那么應該是立馬輸出的。

“應該是立馬輸出 0 到 4 吧。”

 

6.對於promise的考察

 1 setTimeout(function() {
 2   console.log(1)
 3 }, 0);
 4 new Promise(function executor(resolve) {
 5   console.log(2);
 6   for( var i=0 ; i<10000 ; i++ ) {
 7     i == 9999 && resolve();
 8   }
 9   console.log(3);
10 }).then(function() {
11   console.log(4);
12 });
13 console.log(5);

輸出:2 3 5 4 1

考察 JavaScript 的運行機制的,

首先先碰到一個 setTimeout,於是會先設置一個定時,在定時結束后將傳遞這個函數放到任務隊列里面,因此開始肯定不會輸出 1 。

然后是一個 Promise,里面的函數是直接執行的,因此應該直接輸出 2 3 。

然后,Promise 的 then 應當會放到當前 tick 的最后,但是還是在當前 tick 中。

因此,應當先輸出 5,然后再輸出 4 。

最后在到下一個 tick,就是 1 。

所以輸出:2 3 5 4 1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM