舉個例子:
const operations = [] for (var i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
它基本是循環(huán)了5次,將一個函數(shù)添加到operations數(shù)組里面。這個函數(shù)可打印出循環(huán)變量索引值i.
運(yùn)行這些函數(shù)后期望的結(jié)果應(yīng)該是:
0 1 2 3 4
但實(shí)際發(fā)生的是這樣的:
5 5 5 5 5
為什么會有這種情況? 因?yàn)槭褂玫氖莢ar.由于提升了var變量, 上面的代碼等同于
var i; const operations = [] for (i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
因此,在for-of循環(huán)中, i 依然是可見的, 它等于5,并且每次在函數(shù)中涉及到i ,都將使用這個值。
那么我們應(yīng)該如何做讓其變成我們想的這樣呢?
最簡單的方案是用 let 聲明. 在ES2015中介紹到, 它們有很大的幫助,能避免關(guān)于使用var聲明的一些奇怪問題。
簡單的在循環(huán)變量時(shí)將var 變成 let ,能夠很好的運(yùn)行:
const operations = [] for (let i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
這是輸出結(jié)果:
0 1 2 3 4
這是怎么實(shí)現(xiàn)的呢?這是因?yàn)槊看窝h(huán)重復(fù)的時(shí)候,都將重新創(chuàng)造 i ,同時(shí)每個函數(shù)添加operations數(shù)組時(shí),能獲取它本身的i。
記住你不能使用 const在這種情況下, 因?yàn)檫@會導(dǎo)致for在第二次循環(huán)時(shí), 嘗試賦新值報(bào)錯。
另外一個非常普遍的解決這個問題是使用pre-ES6代碼, 同時(shí)它被稱作即時(shí)調(diào)用函數(shù)表達(dá)式 (IIFE).
在這種情況下,你可以包裝整個函數(shù),并將i 綁定在它上面。自這種方式,你正在創(chuàng)造一個能立即執(zhí)行的函數(shù),你從其返回的一個新的函數(shù)。因此我們可以稍后執(zhí)行它。
const operations = [] for (var i = 0; i < 5; i++) { operations.push(((j) => { return () => console.log(j) })(i)) } for (const operation of operations) { operation() }
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com