解決for循環里獲取到的索引是最后一個的問題


  • 方法一

    原理:

    • 利用 setTimeout 函數的第三個參數,會作為回調函數的第一個參數傳入
    • 利用 bind 函數部分執行的特性

    代碼 1:

    for (var i = 0; i < 10; i++) {
      setTimeout(i => {
        console.log(i);
      }, 1000, i)
    }

    代碼 2:

    for (var i = 0; i < 10; i++) { setTimeout(console.log, 1000, i) }

    代碼 3:

    for (var i = 0; i < 10; i++) {
      setTimeout(console.log.bind(Object.create(null), i), 1000)
    }
  • 方法二

    原理:

    • 利用 let 變量的特性 — 在每一次 for 循環的過程中,let 聲明的變量會在當前的塊級作用域里面(for 循環的 body 體,也即兩個花括號之間的內容區域)創建一個文法環境(Lexical Environment),該環境里面包括了當前 for 循環過程中的 i具體鏈接

    代碼 1:

    for (let i = 0; i < 10; i++) {
      setTimeout(() => {
        console.log(i);
      }, 1000)
    }

    等價於

    for (let i = 0; i < 10; i++) {
      let _i = i;// const _i = i;
      setTimeout(() => {
        console.log(_i);
      }, 1000)
    }
  • 方法三

    原理:

    代碼 1:

    for (var i = 0; i < 10; i++) {
      (i => {
        setTimeout(() => {
          console.log(i);
        }, 1000)
      })(i)
    }

    代碼 2:

    for (var i = 0; i < 10; i++) {
      try {
        throw new Error(i);
      } catch ({
        message: i
      }) {
        setTimeout(() => {
          console.log(i);
        }, 1000)
      }
    }
  • 方法四

    原理:

    • 很多其它的方案只是把 console.log(i) 放到一個函數里面,因為 setTimeout 函數的第一個參數只接受函數以及字符串,如果是 js 語句的話,js 引擎應該會自動在該語句外面包裹一層函數

    代碼 1:

    for (var i = 0; i < 10; i++) {
      setTimeout(console.log(i), 1000)
    }

    代碼 2:

    for (var i = 0; i < 10; i++) {
      setTimeout((() => {
        console.log(i);
      })(), 1000)
    }

    代碼 3:

    for (var i = 0; i < 10; i++) {
      setTimeout((i => {
        console.log(i);
      })(i), 1000)
    }

    代碼 4:

    for (var i = 0; i < 10; i++) {
      setTimeout((i => {
        console.log(i);
      }).call(Object.create(null), i), 1000)
    }

    代碼 5:

    for (var i = 0; i < 10; i++) {
      setTimeout((i => {
        console.log(i);
      }).apply(Object.create(null), [i]), 1000)
    }

    代碼 6:

    for (var i = 0; i < 10; i++) {
      setTimeout((i => {
        console.log(i);
      }).apply(Object.create(null), { length: 1, '0': i }), 1000)
    }
  • 方法五

    原理:

    • 利用 eval 或者 new Function 執行字符串,然后執行過程同方法四

    代碼 1:

    for (var i = 0; i < 10; i++) {
      setTimeout(eval('console.log(i)'), 1000)
    }

    代碼 2:

    for (var i = 0; i < 10; i++) {
      setTimeout(new Function('i', 'console.log(i)')(i), 1000)
    }

    代碼 3:

    for (var i = 0; i < 10; i++) {
      setTimeout(new Function('console.log(i)')(), 1000)
    }


免責聲明!

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



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