js闭包问题,为什么是这个结果
新手,对闭包的理解不够,希望大佬们详细说下这段代码的运行过程,原理,机制等
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
新手,对闭包的理解不够,希望大佬们详细说下这段代码的运行过程,原理,机制等
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(13)
阮一峰ES6中有将到这点
他书中的解释
变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。
如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
i
是全局变量 调用a[6]()
的时候去取i
的值 这时候i
早循环到10
了跟下面一个道理
调用的时候才去取值
函数内相关的值是在执行时确定的。
所以执行时去确定i,没有传入i的值,会去外层作用域找,此时i已经在遍历完变成了10。
跟闭包没多大关系。
无论i是几,a[i]();都是10,因为函数作用域变量的值是运行时确定的,不是定义时确定的,当函数执行的时候i已经++到10了。
1、function 并没形成闭包!你都能直接调用该函数,没闭包说法!
2、es6之前,只存在两个作用域: 全局和function
所以i和function的执行环境同,且无闭包。待调用函数时,i = 10
这是函数运行中 执行上下文环境压栈入栈的过程。
去了解一下es6里面的let和var的区别就知道了
额,其实很简单,这个如果说要懂得应该就是函数的作用域了。当函数声明的时候就把函数作用域链的前几层也绑定好了。(因为你刚入门,我就少说点术语)
那问题你中的的函数 function() {console.log(i) }为例子。怎么看他的作用域链呢,先不要看他函数的内部写的什么,先看他在哪里声明,声明时环境能访问到什么(例子中就是 i 和 a)。OK,为了让函数声明后能够访问到,JS会把这个能访问到i和a的环境赋予function,而function又被放在数组a中。
OK,当上栗的循环结束后,我们得到一个包含10个函数的数组。
当我们调用一个数组中的函数。如 a[6](). 当函数执行到要去读取i的时候,在函数的第一层中没有定义。那么JS就会去读取函数作用域的上一层(这个就是函数声明时保存的)
关键来了,尽然函数一声明就要保存一个作用域链,而这些是放在内存中的。你想想这本来开销就大了,如果还保存着当时声明时的值得大小,如读者认为的 6 ,那对内存是极大的开销。所以JS选择保存的是内存的地址。而值是什么,就是执行时内存指向的值。这里是10. 为什么?因为声明函数时候,最后把i的值变为10.
如果你理解的我说的,那么闭包也就懂了。
这段代码没有闭包 因为你的函数执行了的时候已经循环完毕了 i已经加到了10 所以这时不管你调用的是a[]多少的函数 返回的都是10
如要取到当前的值, 可以使用闭包
for ( var i=0; i<10; i++ ) {
}
这里有一个匿名自执行的函数 在i循环的时候就取到了当前的i的值
这个是考的var的作用域,你可以这样试一下,应该就能明白了
http://www.cnblogs.com/wangfu... 去看看王福朋关于闭包的一系列解读吧。适合新手,简单易懂。
js中没有代码块的限制, 所以变量i就是一个全局变量