function test () { var arr = [] for (var i=0; i<10; i++) { arr[i] = function () { console.log(i) } } return arr } var myArr = test() for (var j =0; j < 10; j ++) { myArr[j]() // 10个10 }
要彻底理解这段代码 必须里面所有内容执行顺序都要清楚
我们看for循环的执行步骤
test函数执行之后给我们返回一个数组
var myArr = [ function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, function () {console.log(i)}, ]
我们循环调用10个函数
for (var j =0; j < 10; j ++) { myArr[j]() }
每个函数都执行了console.log(i)
我们要去函数所在的上下文,也就是这个函数所在的位置寻找这个i;
每个函数中没有i 就去函数的外层寻找;
通过10次循环自增,此时的i也就是10
所以打印10个10
这个闭包问题的关键:
1.函数不是立即执行的,所以无法立刻拿到 i 的值,也就无法正确的显示 i
2. 理解for循环,正确的拿到 i 的值
如何解决这个闭包问题,拿到我们想要的值
函数虽然不是立即执行的,但是我们可以让这个函数能够正确的读取到 i 的值
function test () { var arr = [] for (var i=0; i<10; i++) { (function (j) { arr[j] = function () { console.log(j) } } (i)) } return arr } var myArr = test() for (var j =0; j < 10; j ++) { myArr[j]() }
通过理解立即执行函数 将j存在立即执行函数中,也就是函数 function(){console.log(j)} 的外层
当我们访问这个函数function(){console.log(j)} 的时候 就能通过函数的作用域得到j的值