【问题标题】:About executing functions immediately in JavaScript closure关于在 JavaScript 闭包中立即执行函数
【发布时间】:2017-05-20 18:44:00
【问题描述】:

var funcs=[];
for(var i=0;i<3;i++){

  funcs[i]=function(){
    console.log(i);
    };
  }
for(var j=0;j<3;j++){
  funcs[j]();
  }

这样,我知道它会提醒3所有。因为函数是在我被分配到3之后被调用的。

但在下面的代码中,我无法理解为什么会发生这种情况。

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

在我看来,当 i 被赋值为 0 时,第一个函数 setTimeout 将在 i 被赋值为 1 之前执行。

这个循环的顺序我错了吗?

【问题讨论】:

  • 您得到 3x3 的原因完全相同。 “第一个函数 setTimeout 将在 i 赋值为 1 之前执行。” 不,所有函数都在循环终止后执行,此时 i 的值为 3。循环不会等待超时。这实际上从您在未来 2 秒 once 获得所有 3 个函数的输出这一事实中可以明显看出。每个输出之间没有 2 秒的延迟。
  • “3x3”是什么意思?为什么'所有函数都在循环终止后执行'?

标签: javascript jquery loops closures


【解决方案1】:

console.log(i) 将在 for 循环完成后调用,因为var 的方式,for 循环是函数范围的。到达 console.log 语句的时间(2000 毫秒)将是 10。给出预期结果的一种方法是使用let 而不是var。但是,您使用 let 删除了一些浏览器支持。

getify's "You Don't Know Js" book.

for(let i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 2000);
}

【讨论】:

  • 我的问题是为什么“console.log(i) 会在 for 循环完成后被调用”?
  • for 循环立即结束。 console.log 在setTimeout 中,它会在执行前等待。与 for 循环相比,它是异步发生的。 setTimeout 只会阻止其中的内容在计时器到时之前执行。它之外的一切都将继续照常营业。
  • 你的意思是“异步”而不是 setTimeout 等待循环结束?
  • setTimeout 将完成它的计时器并执行,无论 for 循环是否完成,但是 2000 毫秒足以让 for 循环完成对i 的指控。上面和之前的代码独立运行。这听起来更像是异步 javascript 以及 setTimeout 的工作原理而不是函数闭包的问题。
【解决方案2】:

您需要将i 变量放入一个闭包中,否则,它将在每次循环迭代中被重写。 setTimeout 函数也是如此,您也应该将i 变量放入闭包中。

var funcs=[];
for(var i=0;i<3;i++){

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

for(var j=0;j<3;j++){
  funcs[j]();
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 2023-04-04
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多