【问题标题】:One var per function in JavaScript?JavaScript中每个函数一个var?
【发布时间】:2009-08-05 23:01:54
【问题描述】:

我一直在使用 JSLint 让我对我的 JavaScript 感觉不好。顺便说一句,这很棒。有一张支票我不太明白,我想听听您的意见。

来自jslint.com

在具有块作用域的语言中,通常建议在首次使用时声明变量。但是因为 JavaScript 没有块作用域,所以在函数顶部声明函数的所有变量更为明智。 建议每个函数使用一个 var 语句。

最后一句用粗体表示的真正意思是什么?我想我应该像这样声明多个变量?

var foo = 1, bar = 2;

而且,“明智的”部分只是一种防止错误的编程风格,还是还有更多?

感谢您的帮助。

【问题讨论】:

  • 我从stackoverflow.com/users/5445/cmsstackoverflow.com/users/51101/breton 得到了两个极好的答案。我觉得他们俩一起回答了这个问题。我怎样才能对两者都给予信任? :(
  • 顺便说一句,如果您真的想对自己的代码感到难过,请尝试阅读 JSLINT 的源代码并弄清楚它是如何工作的。它非常简单易读,但仍然很神秘。这就像发现宇宙是由方程 2+2 = 计算的分形?
  • 没有任何工具可以自动将代码重新格式化为每个函数样式的一个 var 吗? (但不缩小)
  • Cowboy 对多个 var 语句(我现在很喜欢)有一个很好的反论点:benalman.com/news/2012/05/multiple-var-statements-javascript

标签: javascript lint


【解决方案1】:

问题在于,不管你是否意识到,javascript 都会无形地将所有 var 声明移到函数作用域的顶部。

所以如果你有这样的功能

var i = 5;
function testvar () {
     alert(i);
     var i=3;
}
testvar();

警报窗口将包含未定义。因为在内部,它被改成了这样:

var i = 5;
function testvar () {
     var i;
     alert(i);
     i=3;
}
testvar();

这称为“吊装”。 crockford 如此强烈地提倡将 var 声明放在顶部的原因是,它使代码明显地匹配了它要执行的操作,而不是允许发生不可见和意外的行为。

【讨论】:

  • 这并没有回答问题中以粗体突出显示的部分,即为什么只推荐一个 var 语句。这仅解释了为什么 var 语句应该出现在函数开头的基本原理。任何想法为什么只推荐一个?我很好奇,因为在我看来这会对代码的可读性产生负面影响。
  • @Michael-Lang 好吧,我无法告诉你其他人是如何合理化它的,但就我而言,它迫使我尽可能少地使用变量,这是很好的代码风格。如果一个函数开始有这么多变量,以至于您需要多个 var 语句来保持清晰,我会说这是代码异味(我有罪!)。有一个 var 语句,在参数旁边还可以让您一目了然地在一个地方提供一个函数中的所有元素。将每个放在单独的行上可能不太清楚,并且占用了缩小器无法压缩的空间,并且您可以将东西粘在中间。
  • 在函数顶部声明变量往往会使手动重构变得困难。而不是能够将代码块剪切/粘贴到新函数中,您必须执行两次才能获取变量。它还倾向于导致开发人员在修改代码时留下未使用的变量(不在现场,不在意)。在一个地方声明可能允许使用 Google 闭包编译器之类的东西进行额外的压缩。但是,随着时间的推移,无论变量在何处声明,都可能会进行此类优化。
  • @Michael-Lang - 如果您假设所有变量声明都在函数的开头,那么它们也可以使用单个 var 语句来完成,但我仍然会将个人不同行上的变量名。我发现这比在每一行重复var 更容易阅读。 (相反,我发现同一行上的逗号分隔变量声明更难阅读。)
  • 答案需要更多分号... :)
【解决方案2】:

基本上在 JavaScript 块 ({ ... }) 中不会引入新的作用域,只有函数作用域,因此不会在任何其他语句上创建作用域。

在函数中任意位置引入的变量在函数中随处可见。

例如:

function myFunction(){
  var one = 1;

  if (one){
    var two = one + 1;
  }

  (function () {
    var three = one + two;
  })();

  // at this point both variables *one* and *two* are accessible but 
  // the variable *three* was declared in the scope of a inner function
  // and is not accessible  at this point.
}

在具有块作用域的语言中,建议在第一次使用时声明变量,但由于 JavaScript 没有块作用域,最好在函数顶部声明函数的所有变量。

检查这个article

【讨论】:

  • 您并没有真正解释为什么它更好。它最终确实从仅函数范围得出结论,最好将 vars 放在顶部。但是您忽略了从该事实得出结论的推理步骤。
  • 我刚刚阅读了您链接到的文章,它与 Chetan 犯了同样的错误。重新声明一个 var 是一个 NOOP。它是完全良性的,不会引起任何问题。这并不是说将自己限制在一个 var 语句是没有用的,但是你和这篇文章实际上已经为它提出了一个令人信服的理由。
  • @Breton,它可能会导致问题,因为它通常反映了一个困惑的程序员。它还可以迷惑其他做明智之事并将所有 var 放在函数顶部的程序员。
  • 如果这是推理,那么应该在原始答案中。就目前而言,它就像一个缺少第二个前提的三段论。
  • 小猫毛茸茸的而且很小。所以小猫很可爱。 (尽管它是真的,但这是一个无效的论点,因为你漏掉了“所有毛茸茸的小东西都很可爱”)
【解决方案3】:

块范围的缺乏解释了下面的代码:

var a = 1;
if (something) {
    var a = 2;
}

alert(a); // Alerts "2"

在大多数 C 风格(如语法)语言中,var a = 2 定义只会为 if 块的范围定义“a”。在函数顶部使用单个 var 语句有助于避免 Javascript 的这种怪癖,这种怪癖并不总是像上面那样明显,并且对于 C/C#/Java 程序员来说是意想不到的。

【讨论】:

    【解决方案4】:

    是的,这意味着您在函数的开头声明了所有变量。是单行还是多行是一个选择问题。

    原因在你提到的段落中解释过。 Javascript 变量只有函数级范围。如果您在 if/while/for 块中声明相同的变量,它将被新值覆盖,因为该块不带有新的范围。这与 Java 等语言不同。为避免此类意外,请在函数开头声明您将在函数中使用的所有变量,以免意外“重新声明”和任何东西。

    【讨论】:

    • 我认为重新声明变量不是问题。这不会像在 C(或 java?)中那样抛出错误。事实上它什么也没做。
    • 对不起,我一定更清楚了。我的意思是在块内声明相同的变量名,这在 Java 中是允许的。这个新变量只存在于块内。
    • 啊,是的,我想如果你习惯了块范围的语言,那会是个问题。
    • 我的阅读理解能力今天很糟糕。我完全误解了你原来的帖子。
    • 没问题,我也可以更好地构建我的答案。
    猜你喜欢
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多