带闭包的 JavaScript 作用域:帮助我理解

发布于 2024-09-18 11:17:54 字数 256 浏览 18 评论 0原文

运行以下代码:

for (var i=0; i<3; i++) { 
   setTimeout( function() { console.log(i); } , 500 ); 
}

输出“3”三次。它输出 i 的最终值,而不是创建内部函数时 i 的值。

如果我希望输出为1、2和3,我该如何编写这段代码?如何让它使用定义函数时的 i 值而不是其最终值?

Running the following code:

for (var i=0; i<3; i++) { 
   setTimeout( function() { console.log(i); } , 500 ); 
}

Outputs "3" three times. It's outputting the final value of i as opposed to the value of i when the inner function is created.

If I want the output to be 1, 2, and 3, how would I write this code? How can I get it to use the value of i at the time the function is defined as opposed to its final value?

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

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

发布评论

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

评论(4

朱染 2024-09-25 11:17:54
for (var i=0; i<3; i++) {
   setTimeout( function(val) { return function() { console.log(val); } }(i), 500 );
}

因此,在 setTimeout 时(在我们定义 setTimeout 函数时),我们调用以 val 作为参数的匿名函数。这为每个函数调用创建了一个闭包,将 val 的值存储在我们刚刚调用的函数的范围内。我使用了 self-调用函数,它会立即创建一个闭包

在您提供的代码中,代码创建了一个闭包,但是对于整个代码的更大范围,因此 i 对于整个代码来说是本地的,这意味着在运行时,匿名函数将使用其余代码使用的变量i

for (var i=0; i<3; i++) {
   setTimeout( function(val) { return function() { console.log(val); } }(i), 500 );
}

So, at setTimeout time (at the time we define the function for setTimeout), we're calling the anonymous function taking val as a parameter. This creates a closure for each function call, storing the value of val within the scope of the function we just called. I used a self-invoking function, which creates an immediate closure.

In the code you provided, the code creates a closure, but for the larger scope of the entirety of the code, so i is local to the whole code, meaning that at run-time, the anonymous function will use the variable i that the rest of the code uses.

給妳壹絲溫柔 2024-09-25 11:17:54
function f(i){
  return function(){console.log(i);};
}

for (var i=0; i<3; i++) { 
   setTimeout( 
     f(i)
   , 500 ); 
}
function f(i){
  return function(){console.log(i);};
}

for (var i=0; i<3; i++) { 
   setTimeout( 
     f(i)
   , 500 ); 
}
随波逐流 2024-09-25 11:17:54

显式闭包的现代替代方案(当您有一个双层包装函数时,读起来可能会有点麻烦)是 Function#bind。一旦您获得支持 对于尚未执行 ECMAScript 第五版的浏览器,您可以说:

for (var i=0; i<3; i++) {
    setTimeout(function(i) { console.log(i); }.bind(window, i), 500);
}

windowthis 将在函数内部的值(您不需要这里的 this ,所以我们只使用默认的全局对象)。如果您只是调用另一个函数/方法,就像这里使用 console.log 一样,您可以使用它来完全删除函数表达式:

for (var i=0; i<3; i++) {
    setTimeout(console.log.bind(console, i), 500);
}

The modern alternative to an explicit closure (which can get a bit hairy to read when you've got a double-wrapped function) is Function#bind. Once you've hacked in support for browsers that don't do ECMAScript Fifth Edition yet, you can say:

for (var i=0; i<3; i++) {
    setTimeout(function(i) { console.log(i); }.bind(window, i), 500);
}

the window is the value that this will be inside the function (you don't need a this here, so we just use the default global object). In the case where you're just calling another function/method, like here with console.log, you can use that to excise the function expression completely:

for (var i=0; i<3; i++) {
    setTimeout(console.log.bind(console, i), 500);
}
凉城 2024-09-25 11:17:54

选择:

for (var i=0; i<3; i++) {
   (function(val){
       setTimeout(function() {
           console.log(val);
       },500)
   }(i));
}

alternative:

for (var i=0; i<3; i++) {
   (function(val){
       setTimeout(function() {
           console.log(val);
       },500)
   }(i));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文