首頁  >  文章  >  web前端  >  解析JavaScript迴圈和作用域之間的關係(附程式碼)

解析JavaScript迴圈和作用域之間的關係(附程式碼)

yulia
yulia原創
2018-09-10 18:03:191250瀏覽

我們在工作中常常會用到JavaScript,他與我們的工作有密切的關係。但是JavaScript有一個特點,也許會讓開發者頭痛, 是其循環和作用域相關的,那接下裡就說說他們之間的關係。

舉個例子:

const operations = []
for (var i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}
for (const operation of operations) {
  operation()
}

它基本上是循環了5次,將一個函數加入到operations陣列裡面。這個函數可印出循環變數索引值i.
運行這些函數後期望的結果應該是:
0 1 2 3 4

但實際發生的是這樣的:

5 5 5 5 5

為什麼會有這種情況? 因為使用的是var.由於提升了var變數, 上面的程式碼等同於

var i;
const operations = []
for (i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}
for (const operation of operations) {
  operation()
}

因此,在for-of循環中, i 仍然是可見的, 它等於5,並且每次在函數中涉及到i ,都將使用這個值。
那麼我們應該如何做讓其變成我們想的這樣呢?
最簡單的方案是用let 聲明. 在ES2015中介紹到, 它們有很大的幫助,能避免關於使用var聲明的一些奇怪問題。
簡單的在循環變數時將var 變成let ,能夠很好的運行:

const operations = []
for (let i = 0; i < 5; i++) {
  operations.push(() => {
    console.log(i)
  })
}
for (const operation of operations) {
  operation()
}

這是輸出結果:

0 1 2 3 4

這是怎麼實現的呢?這是因為每次循環重複的時候,都將重新創造i ,同時每個函數添加operations數組時,能獲取它本身的i。
記住你不能使用 const在這種情況下, 因為這會導致for在第二次循環時, 嘗試賦新值報錯。
另外一個非常普遍的解決這個問題是使用pre-ES6程式碼, 同時它被稱作即時調用函數表達式(IIFE).
在這種情況下,你可以包裝整個函數,並將i綁定在它上面。自這種方式,你正在創造一個能立即執行的函數,你從其返回的一個新的函數。因此我們可以稍後執行它。

const operations = []
for (var i = 0; i < 5; i++) {
  operations.push(((j) => {
    return () => console.log(j)
  })(i))
}
for (const operation of operations) {
  operation()
}

以上是解析JavaScript迴圈和作用域之間的關係(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn