3

我在 Sublime Text 2 中安装了一个 Sublimelinter,它很棒。但是它不喜欢以下代码:

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

它说var result = 2;该结果已定义并且已process(result);超出范围使用。是否只是{}将 if 语句误认为是更封闭的范围,还是我真的应该这样做:

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

7 回答 7

6

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

是的,您的程序“Sublimelinter”声称变量超出范围是不正确的。

于 2012-06-05T23:35:59.360 回答
3

这没有错。如果您收到该错误,则说明您result之前在代码中定义过。

您还可以将您的条件简化为此,因此您不必使用结果:

process( condition ? 1 : 2 );
于 2012-06-05T23:37:56.760 回答
1

Javascript 不像许多其他语言那样具有“块范围”。如果是这样,result当您尝试调用时,该变量将不存在,process(result)因为无法在{}定义它的块之外引用它。

但是,javascript 只有函数作用域,其中一个函数中的变量不能被另一个函数访问。在函数中声明变量的位置没有任何意义,因为它仍然可以从该函数内的任何地方访问(没有块范围)。因此,您发布的两个代码片段都等同于运行代码的任何解释器。

第二个更可取,因为它更清楚地显示了将在何处使用变量(在整个函数中)。它还可以防止变量在函数范围内被声明两次,这不一定会导致任何不好的事情发生,但绝对不会导致任何有益的事情发生。您几乎应该总是在较高级别声明一个变量,而不是在不同的较低级别声明两次,尽管这并不重要,因为无论在何处声明变量的范围都是整个函数。

于 2012-06-05T23:44:19.410 回答
0

JavaScript 没有块作用域。变量的范围仅限于定义它们的函数,这意味着当您在if块内声明变量时,它被“提升”到函数的顶部。

由于变量在技术上无论如何都是在函数的顶部定义的,因此将变量声明移动到函数的顶部被认为是一种最佳实践,这样代码的意图就很清楚了。

我会说你的代码不是“错误的”,但它会误导那些阅读代码的人,他们不熟悉 JavaScript 中作用域的工作原理。我肯定会选择第二个版本,因为它实际上反映了代码的执行方式。

这是一篇解释变量提升的好文章。

于 2012-06-05T23:38:01.520 回答
0

事实证明,SublimeLinter 正在使用 JSHint,它可以选择隐藏此警告并解释其存在的原因。


funcscope此选项在稍后从外部访问它们时抑制有关在控制结构内部声明变量的警告。尽管 JavaScript 只有两个真正的作用域——全局和函数——但这种做法会导致语言新手的困惑和难以调试的错误。这是默认情况下,JSHint 警告在其预期范围之外使用的变量的方式。

于 2012-06-07T00:31:56.787 回答
0

在你有 if 语句的函数中声明你的 var 指针一次。就像 ninjagecko 提到的那样,所有的 vars 都会被发送到它们包含的函数的顶部。

然而; 请务必小心,因为如果您两次声明相同的 var,它将重置 var。

于 2012-06-05T23:38:26.310 回答
0

我建议这样做:

var result = MORE_LIKELY_OUTCOME;

if (LESS_LIKELY_CONDITION) {
    result = LESS_LIKELY_OUTCOME;
}

process(result);

通过这种方式,您最初将结果设置为您在大多数情况下所期望的结果。然后,if如果条件发生,该语句将更改结果。

于 2012-06-05T23:39:02.917 回答