声明变量多次

5
for(var i = 0; i < 100; i++){
  var foo = 5;

}

它可以工作......但这样做有什么不好吗?

我知道我可以在外面声明var foo,但是既然我只会在循环中使用它,为什么要那样做呢?


11
实际上,它只被声明一次。所有变量声明都会被提升到它们的作用域顶部(函数或全局作用域的开头)。在JavaScript中,块不会创建作用域。 - bfavaretto
@bfavaretto:至少目前还没有。 - elclanrs
尽管语义与bfavaretto所描述的相同,但我更喜欢“将声明保持靠近”使用位置。这不会改变代码的行为,但是我发现它使代码的意图更清晰,我可以扫描代码以查看是否有什么异常之处。其他人可能持不同意见,这也没关系。 - user2246674
为了更好的理解,请看以下代码:a = "外部"; function f () { a = "内部1"; return a; var a = "内部2" }; alert(f() + " " + a) (这样可以确保在读取变量 a 之前先执行函数 f())。 - user2246674
除非将来您想使用 let 来创建块级作用域,否则请继续使用 var - PSL
显示剩余5条评论
2个回答

4
随着时间的推移,我的个人风格已经发展成为在特定语言的“思维”中“实际存在”的位置声明变量的偏好。对于JavaScript来说,这意味着将变量和函数声明放在语言会提升它们的位置。
这是为了清晰、精确的沟通、理解、可维护性,以保持自己的思维过程与语言的过程平行,只是举几个很好的原因。
所以在这种情况下,我不会将`var foo = 5;`声明放在`for`循环的主体中,简单地说,这并不是它看起来正在做的事情,即它实际上并没有在每次迭代中重新声明/重新作用域变量。(将`var`声明放在for循环头部的初始化部分(初始化;条件;后置)可能更合理,在具有块级变量的语言中放置它的正确位置,例如当JavaScript完成采用块级作用域的let-style声明时。)
注意:
- 这种做法可能看起来不“正常”。我的思维倾向于让变量“靠近”它们的使用,而我的当前做法并不符合我的思维方式。但是作为一个程序员,多年来的困惑、糟糕的沟通、误解、难以维护的代码等经验已经证明,无论语言如何,遵循这种变量声明风格的额外纪律都是值得的。 - 这种做法对我来说有一个额外的好处,它鼓励我保持函数模块化和合理大小。 - 同样地,遵循这种做法可以自动帮助我以合理的方式组织我的代码。例如,如果将我的函数放在前面导致实际工作的代码之前有过多的函数,我因此而感到烦恼,不得不下滑两页来编辑我的程序,那么遵循这种风格会自动给我提供适当的文件结构来组织我的代码。
另外,有人可能会提出一个观点,即某些函数太长,这种做法使得变量声明最终与它们使用的位置相隔数页之远。是的,我看到过这种情况的代码,甚至可能有些情况无法避免。然而,我不禁注意到同样适用于散文作者和计算机程序员的平行关系。随着技能水平的提高,作者的句子长度(和程序员的函数大小)倾向于增加,然后随着技能水平的继续提高,句子长度(和程序员的函数大小)又倾向于缩短。

确保你的方法尽可能简洁,这样你就不需要在很多地方使用那么多变量。但是我更喜欢在使用它们的地方声明变量,即使它们被提升了。 - Ruan Mendes

3

这是不好的,因为它会给人错误的印象,认为ifoo是本地变量。

for(var i = 0; i < 100; i++){
    var foo = 5;
}
foo; // 5

这可能不是简单代码的问题,但如果您使用闭包,则会发现只有一个foo

var counters = [];
for (var i = 0; i < 100; i++) {
    var foo = 5;
    counters.push(function() { foo++; return foo; });
}
counters[0](); // 6
counters[0](); // 7
counters[1](); // 8 (!)

为了在不同的作用域中创建foo,需要引入一个函数:
var counters = [];
for (var i = 0; i < 100; i++) {
    (function() {
        var foo = 5;
        counters.push(function() { foo++; return foo; });
    })();
}
counters[0](); // 6
counters[0](); // 7
counters[1](); // 6

这里有一个现实生活中由此产生的错误示例:for循环中的setTimeout不打印连续值
自JavaScript 1.7以来,您可以使用let关键字(参见MDN)创建真正的本地变量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接