在Javascript中,在if语句内部声明一个变量是否有问题?

3
我安装了Sublimelinter插件在Sublime Text 2中,它非常好用。但是它不喜欢下面的代码:
if(condition){
    var result = 1;
}else{
    var result = 2;
}
process(result);

对于var result = 2;,它指出result已经被定义;而对于process(result);,它则是在超出作用域的情况下使用。这是不是仅仅将if语句中的{}误认为更加封闭的作用域,或者我真的应该像这样做:

var result;
if(condition){
    result = 1;
}else{
    result = 2;
}
process(result);

我不会质疑其他答案,但我认为这是一个不好的习惯。在JavaScript中,“var”的语义有些奇怪,当你有条件代码时,它们只会变得更加奇怪。 - Pointy
1
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting - jasssonpet
我已经找到了它这样做的原因,请看下面我的答案。 - Jake
7个回答

6

不,这并不是“错误”的;根据ECMAScript规范,它将被提升到最近函数定义的顶部。

是的,你的程序“Sublimelinter”有误,它声称该变量超出了作用域。


谢谢,这就是我想确认的。不过我认为第二个例子读起来更好。 - Jake

3

这并没有错。如果你遇到了这个错误,那么你之前在代码中定义了 result

你也可以简化你的条件语句,这样你就不需要使用 result 了:

process( condition ? 1 : 2 );

我之前没有定义result - 这只是我的文本编辑器误将if语句块视为已关闭的作用域。 - Jake
我喜欢您使用三元运算符的解决方案,但我更关心概念层面,这些示例都是简化的。 - Jake

1
Javascript没有像许多其他语言一样的“块级作用域”。如果有的话,当您尝试调用process(result)时,变量result将不存在,因为在定义它的{}块之外引用它是不可能的。
然而,Javascript只有函数作用域,其中一个函数中的变量不能被另一个函数访问。在函数中声明变量的位置根本没有意义,因为它仍然可以从该函数内的任何地方访问(没有块级作用域)。因此,您发布的两个代码片段对于运行代码的任何解释器来说都是等效的。
第二个更可取,因为它更清晰,显示了变量将在整个函数中使用。它还防止变量在函数范围内被声明两次,这可能不一定会导致任何不良后果,但肯定不会带来任何好处。您几乎总是应该在较高级别上声明变量一次,而不是在不同的较低级别上声明两次,即使它并不重要,因为变量的作用域将是整个函数,无论在哪里声明。

0

JavaScript 没有块级作用域。变量的作用域限定于它们所在的函数内,在一个 if 代码块中声明变量时,实际上是将其“提升”到函数的顶部。

由于变量在函数顶部已经定义了,因此最好的做法是将变量声明移到函数顶部,以便代码的意图更加清晰明确。

我认为你的代码并不是“错误”的,但对于不熟悉 JavaScript 作用域的人来说会造成误导。我肯定会选择第二个版本,因为它实际上反映了代码的执行方式。

这里是一篇很好的文章,解释了变量提升。


0

在你的if语句函数内部声明一次var指针。正如ninjagecko所提到的,所有变量都会被发送到其包含函数的顶部。

但是要小心,因为如果你像你声明的那样两次声明同一个变量,它将重置该变量。


0
我建议这样做:
var result = MORE_LIKELY_OUTCOME;

if (LESS_LIKELY_CONDITION) {
    result = LESS_LIKELY_OUTCOME;
}

process(result);

这样,您最初将结果设置为大多数情况下所期望的内容。 然后,如果条件发生变化,if语句将更改结果。


0
原來SublimeLinter使用了JSHint,該工具有選項可以抑制此警告並解釋其存在的原因。
funcscope 选项可以抑制有关在控制结构内部声明变量,然后从外部访问它们的警告。尽管 JavaScript 只有两个真正的作用域——全局和函数——但这种做法会导致新手对语言的困惑和难以调试的错误。因此,默认情况下,JSHint 会警告超出其预期范围使用的变量。

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