我正在尝试理解为什么我收到以下错误,而不是 如何解决它。
将以下代码传递给JSLint或JSHint会产生错误'错误'已定义。
/*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
子句采用的是标识符 绑定到异常。此外,catch
的语义生成规则是指参数,它将标识符作为参数传递出去。
这似乎向随意的读者建议上面的代码是有效的,也许lint工具有一个bug。
即使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,事实证明这是一个非常有效的理由。请参阅下面的答案。
答案 0 :(得分:10)
写给JSLint的作者Douglas Crockford,关于这个问题。
毕竟这是一个非常正确的理由......
道格拉斯写道:
Catch变量的范围不正确,因此我建议您在每个变量中使用不同的名称。
如果你看this similar StackOverflow question,你会注意到PleaseStand开始触及它。 并非所有浏览器(尤其是历史浏览器)都能正确或一致地处理范围。
JSLint认识到您的代码可以在一个浏览器中工作,但在另一个浏览器中不能工作,留下一个非常讨厌和微妙的错误来追踪。 警告是真实的。
通过使用一个不同的名称,是的,根本不会感觉干净或简洁,因为它不是,恰好是没有遇到问题的普遍方式。
谢谢道格拉斯的澄清!神秘解决了。
答案 1 :(得分:3)
规范很清楚,任何定义了catch语句的名称都只会影响周围的名称。除此之外,我不认为这些错误仅仅是一个警告。只是使用纯粹的直觉我相信这只是那些Lint工具的设计者的过分热情分析。
由于catch块引入了新的作用域,因此使用相同的名称只会隐藏封闭作用域中的任何类似名称。如果您了解语义,这不一定是坏事。如果您在假设封闭式err
可访问的情况下进行编码,则需要更改您的假设。
<强>规范强>
生产Catch:catch(Identifier)Block的评估如下:
注意无论控件如何离开Block,LexicalEnvironment总会恢复到以前的状态。
答案 2 :(得分:2)
检查这个答案: JSLint complaining about my try/catch
如前所述,try
打开了一个新的块范围。见https://developer.mozilla.org/en/JavaScript/Reference/Scope_Cheatsheet
事实上,文档的顶部解释说它不是全部标准,但在ES5, section 12.14中,执行catch
块的部分明确将MDC的描述定义为标准:
无论控制如何离开Block,LexicalEnvironment总是恢复到以前的状态。
答案 3 :(得分:0)
如果稍后需要引用错误,可以在顺序try-catches中重复使用相同的参数名称时出现问题。
如果调用了多个catch,则只有最后一个将在finally或函数范围表达式的范围内。
jsLint是保守的 - 如果你可以阻止可能搞砸一个独特的变量,为什么不使用呢?