【发布时间】:2011-08-31 07:26:21
【问题描述】:
我试图了解为什么我收到以下错误,而不是如何解决它。
将以下代码传递给JSLint 或JSHint 会产生错误'err' is already defined。
/*jslint white: true, devel: true, onevar: true, browser: true, undef: true, nomen: true, regexp: true, plusplus: true, windows: true, bitwise: true, newcap: true, strict: true, maxerr: 50, indent: 4 */
function xyzzy() {
"use strict";
try { /*Step 1*/ } catch (err) { }
try { /*Step 2*/ } catch (err) { }
}
这里的明显假设是catch 的行为或应该像函数一样行为。因此,err 既不是全局变量,也不是xyzzy 的局部变量,而是catch 块的参数。
在浏览ECMA-262 Standard 时,第 12.14 节描述 try 语句 表明 catch 子句采用 标识符,该标识符是 绑定的 em> 例外。此外,catch 的语义生成规则引用了一个 parameter,该参数通过调用 Identifier 作为 argument。
这似乎向普通读者表明上述代码是有效的,并且可能 lint 工具存在错误。
即使IntelliJ 最严格的 JavaScript 代码检查分析也没有报告 err 被重新定义存在问题。
更多的问题是,如果它是一个变量范围问题,那么人们可能会推测err 正在流入全局空间,这会带来许多其他问题,而应该提前声明它,像这样:
/*jslint white: true, devel: true, onevar: true, browser: true, undef: true, nomen: true, regexp: true, plusplus: true, windows: true, bitwise: true, newcap: true, strict: true, maxerr: 50, indent: 4 */
function xyzzy() {
"use strict";
var err; // DECLARE err SO IT IS CERTAINLY LOCAL
try { /*Step 1*/ } catch (err) { }
try { /*Step 2*/ } catch (err) { }
}
但这只会在每个 catch 语句中导致两个关于 err 的错误,使问题变得更糟,并可能引入 variable shadowing。
lint 工具建议每个catch 块不仅引入它自己的词法范围,还引入一个新变量。这不可能。
简单地制作err1,err2,...来安抚静态分析工具只会隐藏症状,不会有助于更简洁的代码。
JavaScript 专家:这是 lint 工具中的错误,JavaScript 规范的一个黑暗角落,还是对这里发生的事情的根本误解?
更新:写信给 JSLint 的作者 Douglas Crockford,事实证明这个警告是有充分理由的。请参阅下面的答案。
【问题讨论】:
-
限制对来自 JSLint 的投诉的信任程度非常重要。
-
@Pointy - 理解,但迄今为止,JSLint 在涉及微妙问题时已经提出了一些非常有效的观点,这就是我使用它的原因。如果它实际上是一个错误,我会像过去一样联系 Douglas,但我想在这样做之前我会进一步探索这个问题。它总是有助于从内到外理解一种语言,以及 linter 产生的警告。只有当我知道 lint 工具出错时,我才会忽略这些警告,虽然不太可能,但这是可能的。
-
提醒所有人:目标不是关于范围、catch 块中发生的事情或其他变量的阴影。这就是为什么 lint 将要捕获的参数视为唯一的变量声明。是否有一个微妙的用例为什么 lint 会这样做?如果它是合法的,仅仅忽略它是不够的,但如果这样做的做法可能会引入一个微妙的错误。这就是探索,这反过来又决定了适当的修复。
-
好吧,规范很清楚标识符绑定在“新的声明性环境”中,因此必须将其视为样式注释,而不是对实际危险代码的警告。 (当然,有人可能会认为有问题的编码风格是“危险的”,但这是在意见范围内。)(在我看来 :-)
-
@Point - 我肯定会接受“风格”作为可接受的答案;我只需要弄清楚这种风格会出现问题的“原因”。 (见过 JSLint 如何处理 switch/case 语句缩进吗?感觉很陌生,过了一会儿才有意义。)我认为检查是在某人被某些非常邪恶和微妙的东西咬伤之后添加的。我很想知道那是什么。
标签: javascript scope try-catch jslint