js闭包问题,为什么是这个结果

发布于 2022-09-06 06:20:50 字数 175 浏览 23 评论 0

Image

新手,对闭包的理解不够,希望大佬们详细说下这段代码的运行过程,原理,机制等

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

风筝在阴天搁浅。 2022-09-13 06:20:50

阮一峰ES6中有将到这点

他书中的解释
变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。

如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

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

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

递刀给你 2022-09-13 06:20:50

i是全局变量 调用a[6]()的时候去取i的值 这时候i早循环到10
跟下面一个道理

var i = 0;
var a = function(){
    console.log(i)
}
i=10;
a()//10

调用的时候才去取值

影子的影子 2022-09-13 06:20:50

函数内相关的值是在执行时确定的。
所以执行时去确定i,没有传入i的值,会去外层作用域找,此时i已经在遍历完变成了10。
跟闭包没多大关系。

堇色安年 2022-09-13 06:20:50

无论i是几,a[i]();都是10,因为函数作用域变量的值是运行时确定的,不是定义时确定的,当函数执行的时候i已经++到10了。

演出会有结束 2022-09-13 06:20:50
var a = [];
for (var i=0;i<10;i++) {
    a[i] = function () {     // 这里的i具有迷惑意义,其实没什么作用
        console.log(i);
    };
}                            //运行到这里i为10
a[6](); // 10                //到这里a[0]~a[10]都是function(){console.log(10)},由此得出结果。
蒲公英的约定 2022-09-13 06:20:50

1、function 并没形成闭包!你都能直接调用该函数,没闭包说法!
2、es6之前,只存在两个作用域: 全局和function

所以i和function的执行环境同,且无闭包。待调用函数时,i = 10

戏剧牡丹亭 2022-09-13 06:20:50

这是函数运行中 执行上下文环境压栈入栈的过程。

你不断调用a[i], 都是从function(){ console.log(1) } 压栈,然后 function(){ console.log(2) } 压栈,然后function(){ console.log(3) }。一直到function(){ console.log(10) }压栈

http://www.cnblogs.com/wangfupeng1988/p/3992795.html
可以看看这个系列
一身仙ぐ女味 2022-09-13 06:20:50

去了解一下es6里面的let和var的区别就知道了

我喜欢麦丽素 2022-09-13 06:20:50

额,其实很简单,这个如果说要懂得应该就是函数的作用域了。当函数声明的时候就把函数作用域链的前几层也绑定好了。(因为你刚入门,我就少说点术语)
那问题你中的的函数 function() {console.log(i) }为例子。怎么看他的作用域链呢,先不要看他函数的内部写的什么,先看他在哪里声明,声明时环境能访问到什么(例子中就是 i 和 a)。OK,为了让函数声明后能够访问到,JS会把这个能访问到i和a的环境赋予function,而function又被放在数组a中。
OK,当上栗的循环结束后,我们得到一个包含10个函数的数组。
当我们调用一个数组中的函数。如 a[6](). 当函数执行到要去读取i的时候,在函数的第一层中没有定义。那么JS就会去读取函数作用域的上一层(这个就是函数声明时保存的)
关键来了,尽然函数一声明就要保存一个作用域链,而这些是放在内存中的。你想想这本来开销就大了,如果还保存着当时声明时的值得大小,如读者认为的 6 ,那对内存是极大的开销。所以JS选择保存的是内存的地址。而值是什么,就是执行时内存指向的值。这里是10. 为什么?因为声明函数时候,最后把i的值变为10.
如果你理解的我说的,那么闭包也就懂了。

哥,最终变帅啦 2022-09-13 06:20:50

这段代码没有闭包 因为你的函数执行了的时候已经循环完毕了 i已经加到了10 所以这时不管你调用的是a[]多少的函数 返回的都是10
如要取到当前的值, 可以使用闭包
for ( var i=0; i<10; i++ ) {

(function(i){
    a[i] = function () {
        console.log(i)
    }
})(i)

}
这里有一个匿名自执行的函数 在i循环的时候就取到了当前的i的值

沦落红尘 2022-09-13 06:20:50

这个是考的var的作用域,你可以这样试一下,应该就能明白了

var a = []
console.log(index) // undifined
console.log(b) // b is not defined
for (var index = 0; index < 10; index++) {
  a[index] = function() {
    // 此时无论这个方法内怎么写都无所谓,不执行的
    console.log(index)
  }
}
a[6]() // 这时执行方法,而index已经for完成了
月寒剑心 2022-09-13 06:20:50

http://www.cnblogs.com/wangfu... 去看看王福朋关于闭包的一系列解读吧。适合新手,简单易懂。

残花月 2022-09-13 06:20:50

js中没有代码块的限制, 所以变量i就是一个全局变量

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文