for |
您所在的位置:网站首页 › for循环内定义变量 › for |
在初始化块中声明变量与在上层作用域中声明它有着重要的区别,尤其是在循环体中创建闭包时。例如,对于以下代码: 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、2initialization 内部的 i 变量与每次迭代中的 i 变量是不同的,包括第一次。因此,在这个例子中,getI 返回 0,即使在迭代中 i 的值已经递增了: jsfor (let i = 0, getI = () => i; i i, incrementI = () => i++; getI() |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |