前言
ES5,中不存在代碼塊的作用域,如下代碼所示,變量i是var命令聲明的阵具,在全局范圍內(nèi)都有效颁独,所以全局只有一個變量i。每一次循環(huán)拾并,變量i的值都會發(fā)生改變,導(dǎo)致運(yùn)行時輸出的是最后一輪的i的值,也就是 4
var a = ["a","b","c","d"]
var b = [];
var c = [1000,200,1300,400];
for(var i=0;i<a.length;i++){
var t = a[i];
b.push(
new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(t,i)
resolve();
},c[i])
})
)
}
Promise.all(b).then(() => {
console.log("all");
})
預(yù)期的結(jié)果是控制臺打印出
b 1
d 3
a 0
c 2
all
但卻打印出
d 4
d 4
d 4
d 4
all
解決的辦法
(1)用let變量定義替換var
ES中l(wèi)et為 JavaScript 新增了塊級作用域,下面代碼中,變量i是let聲明的鹏浅,當(dāng)前的i只在本輪循環(huán)有效嗅义,所以每一次循環(huán)的i其實都是一個新的變量.
for(let i=0;i<a.length;i++){
let t = a[i];
b.push(
new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(t,i)
resolve();
},c[i])
})
)
}
示例
(2)通過function的bind方法
JavaScript中函數(shù)是存在作用域的,函數(shù)用call()、apply()隐砸、bind()這些方法去改變this的指向之碗。
for(var i=0;i<a.length;i++){
var t = a[i];
b.push(
new Promise((function(resolve,reject){
setTimeout(()=>{
console.log(this.t,this.i)
resolve();
},c[i])
}).bind({t:t,i:i}))
)
}
示例
(3)通過array的forEach方法
ES5為數(shù)組提供了forEach迭代方法,對數(shù)組每一項運(yùn)行給定函數(shù),這個方法沒有返回值
a.forEach((t,i)=>{
b.push(
new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(t,i)
resolve();
},c[i])
})
)
})