for 您所在的位置:网站首页 for循环中能省略的表达式有什么 for

for

2024-06-29 22:43| 来源: 网络整理| 查看: 265

在初始化块中声明变量与在上层作用域中声明它有着重要的区别,尤其是在循环体中创建闭包时。例如,对于以下代码:

jsfor (let i = 0; i { console.log(i); }, 1000); }

正如预期的那样,它打印了 0、1 和 2。但是,如果变量是在上层作用域中定义的:

jslet i = 0; for (; i { console.log(i); }, 1000); }

它打印了 3、3 和 3,因为每个 setTimeout 创建了一个新的闭包,它引用了 i 变量,但是如果 i 不是循环体的局部变量,那么所有的闭包都会引用同一个变量,并且由于 setTimeout 的异步性质,它可能在循环已经退出之后才被调用,导致所有队列里的回调函数的 i 值都被设置为 3。

如果你使用 var 语句来初始化,那么变量声明将只作用于函数作用域,而不是词法作用域(即它不会局限于循环体)。

jsfor (var i = 0; i { console.log(i); }, 1000); } // 打印 3、3、3

初始化块的作用域范围可以理解为声明发生在循环体内部,但实际上只能在 condition 和 afterthought 部分中访问。更准确地说,let 声明是 for 循环特有的——如果 initialization 是 let 声明,那么每次循环体执行完毕后,都会发生以下事情:

使用 let 声明新的变量会创建一个新的词法作用域。 上次迭代的绑定值用于重新初始化新变量。 afterthought 在新的作用域中执行。

因此,在 afterthought 中重新分配新变量不会影响上一次迭代的绑定。

新的词法作用域会在 initialization 之后、condition 第一次被判定之前创建。这些细节可以通过创建闭包来观察到,闭包允许在任何特定点获取绑定。例如,在以下代码中,在 initialization 部分创建的闭包不会被 afterthought 中 i 的重新分配更新:

jsfor (let i = 0, getI = () => i; i i; i i) { console.log(getI()); } // 打印 0、1、2

initialization 内部的 i 变量与每次迭代中的 i 变量是不同的,包括第一次。因此,在这个例子中,getI 返回 0,即使在迭代中 i 的值已经递增了:

jsfor (let i = 0, getI = () => i; i i, incrementI = () => i++; getI()


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有