循环和关闭。 For和Var

时间:2017-11-19 00:12:23

标签: javascript loops closures var let

我找到了许多解释这个问题的主题,关于如何使用var来修复以下代码,就像这个一样 http://conceptf1.blogspot.com/2013/11/javascript-closures.html或此JavaScript closure inside loops – simple practical example

但是我真的不明白为什么在使用var时工作不起作用而且在使用let时工作。

var funcs = [];        
for (var i = 0; i < 3; i++) {        //  let's create 3 functions
  funcs[i] = function() {            //  and store them in funcs
    console.log("My value: " + i);   //  each should log its value.
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j]();                        //  and now let's run each one to see
}
// outputs 3 3 3

我真的不知道......

3 个答案:

答案 0 :(得分:1)

ES6's let是块范围,这意味着它像许多其他传统语言一样拥有{}内的自己的范围。但相比之下,var是代码中的全局变量。

在第一个for循环中,function仅被分配给func[i] 3次,最终值为3但未执行。如果您在第一个loop内执行该函数,您将得到预期的输出,如:

&#13;
&#13;
var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = function() {          // and store them in funcs
    console.log("My value: " + i); // each should log its value.
  };
  funcs[i](); // execution of func
}
&#13;
&#13;
&#13;

所以,重要的是你的函数在哪个上下文中执行。

现在,在您的代码中第一次执行funcs[j]()时,i的值已经是3。如果要记录递增的值,则必须将其作为参数传递,如下所示:

&#13;
&#13;
var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = function(j) {          // and store them in funcs
    console.log("My value: " + j); // each should log its value.
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j](j);                      // and now let's run each one to see
}
&#13;
&#13;
&#13;

答案 1 :(得分:0)

因为var是函数范围的(即具有周围函数的范围),而let&amp; const是块范围的 - 因此在每个块中都有自己的值(可以是if - 或else - 阻塞或循环的每次迭代(如您的情况)。块范围变量未在块外定义。函数范围的变量一直持续到函数结束。

你的i变量是功能范围的,这意味着一旦你的循环完成,它仍然存在于第一个循环之外。值为3。因此,一旦调用了数组函数,它就会从上部范围(i)&amp;中获取3。输出它。例如,如果您使用let,则每次迭代都会得到一个新的绑定。您的i值将保留初始声明值。

编辑: 因此,为了输出顺序值,您需要将var替换为let

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    // now `i` is bound to the scope & keeps its initial value
    console.log("My value: " + i); 
  };
}

答案 2 :(得分:0)

let不同,var在循环范围之外被提升。实际上,您的i变量将始终等于最后一次迭代(在您的示例中为3)。 let没有这个问题,因为它没有被吊起。