搜尋

首頁  >  問答  >  主體

javascript - js 入坑題目:setTimeout()函數執行完結果卻是五個6的原因是?

setTimeout()函數執行完結果卻是 五個6 的原因是?

 for (var i = 1; i <= 5; i++) {
        setTimeout(function timer() {
            console.log(i);
        }, i * 1000);
    }
// 其实我们想得到的结果是1,2,3,4,5,结果却是五个6

雖然用js 閉包解決了問題,得到想要的1,2,3,4,5,但還是不明白上述的程式碼為什麼會出現五個6?

 for (var i = 1; i <= 5; i++) {
        (function(j) {
            setTimeout(function timer() {
                console.log(j);
            }, j * 1000);
        })(i);
        
//通过一个立即执行函数,为每次循环创建一个单独的作用域
黄舟黄舟2827 天前834

全部回覆(3)我來回復

  • PHPz

    PHPz2017-05-19 10:49:29

    首先需要明白的一點JS的任務機制是隊列機制。

    所以沒走一次for循壞只是把setTimeout這個任務放到隊列後面,也就是setTimeout裡面執行的程式碼只會在執行完for循壞才會執行,所以那個時候i的值就是不滿足for循壞的值,才會去執行setTimeout的程式碼。

    個人看法,有什麼說的不對的歡迎指出

    回覆
    0
  • 天蓬老师

    天蓬老师2017-05-19 10:49:29

    var 改為 let 即可

    var 是全域定義,i 沒有構成閉包,log(i)都是列印i的最終值 6

    let 是區塊級定義域

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

    回覆
    0
  • 为情所困

    为情所困2017-05-19 10:49:29

    setTimeout有2個特性,它的this與上下文的this分離,它的呼叫是非同步的。

    這裡就是【非同步】造成的,for循環會先全部完成,再執行setTimeout,因為for循環每次執行到最後都是6了- -所以自然setTimeout再調用i就是五個6

    解決方法一:

    var 换 let

    解決方法二:

    楼主自己用的闭包

    解決方法三:

    //类似于方法二,使用setTimeout的第三个参数直接传参
      for (var i = 1; i <= 5; i++) {
        setTimeout(function(i) {
          console.log(i);
        }, i * 1000,i);
      }

    回覆
    0
  • 取消回覆