var
在循环头中声明 with 的问题在于它具有欺骗性。看起来您正在声明一个变量,其范围仅限于for
循环,而它实际上存在于函数中的任何地方 - 包括在声明之前:
var i = 1;
function foo() {
console.log(i); // 'undefined'
for (var i=1; i<100; ++i) {
}
}
即使console.log
调用发生在 local 的声明之前i
,它仍然在它的范围内,因为它在同一个函数内。因此i
,尚未为其分配任何值的 local 是传递给log
. 这可能令人惊讶。对于不熟悉 Javascript 范围规则的任何人来说,这肯定不是显而易见的。
从ECMAScript 2015开始,有一种更好的方式来声明变量:let
. 声明的变量let
是包含它们的块的局部变量,而不是整个函数。因此,上述代码的这个版本1
将按预期打印:
let i=1; // could use var here; no practical difference at outermost scope
function foo() {
console.log(i); // 1
for (let i=1; i<100; ++i) {
}
}
因此,现代 Javascript 中的最佳实践是使用let
而不是var
. 但是,如果您坚持使用 ECMAScript 2015 之前的实现,那么在函数顶部声明所有变量而不是等到第一次使用时会更容易混淆。