es5中使用在
for-in
for
循環中注冊異步事件,異步事件中的i
總是最后一個值。使用es6的let
const
可以解決
let obj = {a: 1,b: 1,c: 1
}// es5 for循環中 var聲明 i
let funcs = []
for (var key in obj) {funcs.push(() => {console.log(key)})
}
funcs.forEach(func => {func()
})
// c c c// es6 for循環中 let聲明 i
let funcs1 = []
for (let key in obj) {funcs1.push(() => {console.log(key)})
}
funcs1.forEach(func => {func()
})
// a b c
復制代碼
每次循環時,let
會聲明都會創建一個新變量key
,并將其初始化為key
的當前值,所以循環內部創建的每個函數都能得到屬于他們自己的i的副本。 值得一提的是,let
聲明再循環內部的行為是標準中專門定義的,他不一定與let
的不提升特性有關系,事實上,早起的let實現并不包含這一行為,是后來加入的。
而下邊這個例子也證實了這一流程
let funcs1 = []
for (const key in obj) {funcs1.push(() => {console.log(key)})
}funcs1.forEach(func => {func()
})
// a b c
復制代碼
const
定義的key
是不能重新賦值的,但在循環中一直變化,并沒有報錯。是因為每次迭代都是新創建一個變量而不是修改已有變量
但const
在下面循環中會報錯,因為迭代一次后,i++
修改了const
聲明的i
let funcs = []
let arr = [1, 2, 3]
for (const i = 0; i < arr.length; i++) {funcs.push(function () {iconsole.log(i)})
}
funcs.forEach(() => {func()
})
// 1 2 3
復制代碼