我正在研究JavaScript教程。为了显示let和var的区别,给出了以下示例,该示例生成一堆盒子,如果单击一个盒子,则输出盒子的索引:
我创建了以下代码笔:https://codepen.io/run_the_race/pen/aXJQmp?editors=1111 感兴趣的主要部分是:
for (var i=0; i < 20; i++)
{
var div = document.createElement("div");
div.onclick = function() {
console.log("You clicked on box #:" + i);
}
document.querySelector("section").appendChild(div);
}
如果使用var声明i,则所有框之间共享相同的索引值。 如果使用let来声明i,那么本教程将说我具有块范围,因此将为每个索引创建一个不同的变量。
那么我的问题是,如果我在每次循环执行中都是一个单独的变量,那么如果我在循环中递增i会怎样改变迭代次数呢?
它似乎对于每个迭代都是独立的(不像使用var声明时那样共享),但是由于更改它会影响迭代而被共享。我了解发生了什么,但我不明白为什么。
编辑:尽管其他文章都讲解了本教程所解释的内容,但并未解释每次迭代,在上一次迭代结束时再次使用i的值声明i,如@Pointy所述。我也简化了一点。
答案 0 :(得分:2)
在for
循环第一个表达式可以与声明一个或多个变量let
,其被称为词法声明在spec。变量存在于为包含循环主体的语句块创建的上下文中。在第一次迭代中,变量以其初始值设定项表达式计算得出的值或undefined
开始。
在第一次迭代的结尾对for
循环标头的第三个表达式求值后,将为该块创建一个新的上下文,它将包含在词法声明中声明的所有相同变量。块开始执行用于第二次迭代之前从旧的上下文的每个变量的值被复制到新的。直到循环结束该过程发生在每一次迭代。
答案 1 :(得分:1)
尝试一下,这样可以确保onclick函数接收到的变量在创建时是相同的:
for (var i=0; i < 20; i++)
{
console.log(i);
var div = document.createElement("div");
var str = "You click on box #:" + parseInt(i);
(str => {
div.onclick = function() {
console.log(str);
}
})(str)
document.querySelector("section").appendChild(div);
}