js闭包问题求助


var a = [];
        for(var i = 0; i < 10; i++) {
            a[i] = (function(j) {
                return function() {
                    console.log(j)
                }
            })(i)
        }
        a[6]()

对于这个 我有点不理解 这样写是对的


var a = [];
        for(var i = 0; i < 10; i++) {
            a[i] = function() {
                console.log(i)
            }
        }
        a[6]()

这样写会是10 是什么原因啊 求讲一下原理 是不是因为这个函数没有立即执行 然后最后循环结束了 这个函数才被执行 然后就成为10了?

阅读 2.9k
7 个回答

先来说第二段为什么不对。

你应该知道js里变量的作用域的,for循环里面的匿名函数里面引用的i,相当于就是一个全局变量,循环结束之后的值是10,所以接下来无论你调用a几都是输出10,因为i只有一个在那里。


再说第一个为什么正确

同样i还是相当于全局变量只有一个,但是在for循环里,通过一个立即执行的函数(参数j的那个函数)返回了一个新的function,同时这个新的function会输出j的值。因为参数j是局部变量啊,每次循环都是新的function不会互相影响,所以能正常输出。


有点难措辞。

那个i是全局变量,处于全局作用域之中,闭包的话,产生了新的作用域,那个值并不在全局当中
关于作用域

新手上路,请多包涵

你设置断点你就知道了,在for循环时不执行function里的内容,一直到循环结束。
所以当执行a[6]()打印出来的值是for循环结束时i的值,已经自增到10.

因为你第二种写法for循环内部只是函数的定义,函数并没有运行。
a[6](),这句代码是运行函数。运行的时候是要去找变量i的,但for循环结束之后,变量i的值就是10了,所以结果就是10了

第一写法,
a[i] = (function(j) {

            return function() {
                console.log(j)
            }
        })(i)
        这个叫做匿名函数自执行,函数会自动执行一遍,i是等于j的,而且在return里面调用了j,所以每一个j都会存进内存中,但不是同一个j
        第二种写法:
         a[i] = function() {
            console.log(i)
        }
    }
    只是给每一个对应数值的值添加函数,函数并没有执行,(函数调用的时候才会执行),所以i只会有一个全部变量i,所以你不管怎么调用,或者修改都是修改同一个i。所以最终答案是10

和作用域有关
平常情况下js能创建新作用域的只有函数
匿名自执行函数创建了新的作用域,将i传入该作用域,使得该作用域中保存了该数字,返回的函数能够访问该变量
不闭包的话,函数访问i,i是一个引用,所有的函数中的i其实是同一个

建议看看《你不知道的JavaScript》这本书,讲解的非常透彻

推荐问题
宣传栏