var a = []
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i)
}
}
a[5]() // 10
以上代码的执行顺序可以理解为
在循环中声明了function a[0-9],但是function a[0-9]并没有执行,当function a[0-9]执行的时候循环已经结束,并且已经++,所以当function a[0-9]执行的时候拿到的i是10,出现这样的原因便是因为for没有块级作用域,所以只能拿到全局变量 i
我们再看下面这种情况
for (var i = 0; i < 10; i++) {
console.log(i)
}
// 0 1 2 3 4 5 6 7 8 9
诶,那我这里怎么又能是正常的呢,仔细看,其实
a[i] = function () {
console.log(i)
}
console.log(i)
其实作为函数的内容他们都已经是被正确的执行了,只不过前面第一个例子执行的内容是声明了几个函数,而后面的例子执行的内容却是直接打印了i的内容。
那我们要如何去解决上面的问题呢
解决方案一
使用IFFE(匿名函数自执行)
将上面的代码进行修改
var a = []
for (var i = 0; i < 10; i++) {
a[i] = (function (i) {
return function () {
console.log(i)
}
})(i)
}
a[5]() // 5
为什么这样子就可以正确执行呢,继续按照我们刚才的思路,可以理解成
a[0] = (function(0){
return funtion(){
console.log(0) // 这里的0就是参数0
}
})(0) //循环第一次,执行循环中的内容
a[1] = (function(1){
return funtion(){
console.log(1) // 这里的1就是参数1
}
})(1) //循环第二次,执行循环中的内容
所以当我执行a[5]时拿到的不再是for循环执行完毕后的 i(10),因为在我执行a[5]时我拿到的自执行函数的参数中的 i,我在循环中已经将每一个 i 已参数的形式传进了自执行函数中
解决方案二
es6 let块级作用域
var a = []
for (let i = 0; i < i; i++) {
a[i] = function () {
console.log(i)
}
}
a[5]() // 5
同样为什么这样子也可以正确执行呢,我们继续分析代码的执行
{
let i = 0;
a[i] = function(){
console.log(i) // 1
}
} //循环第一次
{
let i = 1;
a[i] = function(){
console.log(i) // 2
}
} //循环第二次
这样子相信大家就很容易理解了,这就是let创建块级作用域的作用域,每个i都只能在相应的作用域去拿到
以上也是个人的理解,如果有什么问题不对的也请纠正,请大家带着思考去看文章,不想被人说误人子弟吼吼吼