问题描述
我试图了解为什么我得到以下错误,而不是解决方法。
将以下代码传递给JSLint或JSHint会产生错误“'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\";
try { /*Step 1*/ } catch (err) { }
try { /*Step 2*/ } catch (err) { }
}
这里明显的假设是catch
的行为或应该像函数一样。因此,err
既不是全局变量,也不是xyzzy
的局部变量,而是catch
块的参数。
在浏览ECMA-262标准时,描述“ 5”语句的12.14节指示“ 1”子句采用绑定到异常的标识符。另外,“ 1”的语义产生规则指的是传递来的参数,该参数将标识符称为参数。
对于临时读者来说,这似乎暗示上述代码是有效的,并且棉绒工具可能存在错误。
甚至IntelliJ最严格的JavaScript代码检查分析也没有报告重新定义ѭ2的问题。
更令人担忧的是,如果这是一个可变的范围界定问题,那么人们可能会猜测ѭ2正在渗入全球空间,这带来了一系列其他问题,而应该事先声明它,例如:
/*jslint white: true,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
的两个错误,这使问题变得更糟,并可能引入可变阴影。
棉绒工具建议每个ѭ1块不仅引入其自身的词法范围,还引入一个新变量。这是不对的。
简单地使用err1
,err2
...来放置静态分析工具仅能掩盖症状,并且不会有助于编写更清晰的代码。
JavaScript Gurus:这是皮棉工具中的错误,JavaScript规范的阴暗角还是对这里发生的事情的根本误解?
更新:写给JSLint的作者道格拉斯·克罗克福德(Douglas Crockford),事实证明,出现此警告的理由很充分。请参阅下面的答案。
解决方法
写给JSLint的作者道格拉斯·克罗克福德(Douglas Crockford)谈这个问题。
毕竟有一个非常合理的理由...
道格拉斯写道:
捕获变量的作用域不正确,因此我建议您在每个变量中使用不同的名称。
如果您看到类似的StackOverflow问题,您会注意到PleaseStand开始对此进行探讨。并非所有的浏览器,尤其是历史悠久的浏览器都能正确或一致地处理作用域。
JSLint认识到您的代码可能在一种浏览器中有效,但在另一种浏览器中无效,从而留下了一个非常讨厌和微妙的错误来进行跟踪。该警告是真实的。
通过使用一个不同的名称,是的,因为它不是,所以不会感到干净或简洁,这恰好是避免遇到问题的通用方法。
谢谢道格拉斯的澄清!谜团已揭开。
,该规范非常清楚,任何定义catch语句的名称都不会对周围的名称造成阴影。除此之外,我不会将这些错误视为警告。仅凭直觉,我相信这只是这些Lint工具设计者的过度热情分析。
由于catch块引入了一个新的作用域,因此使用相同的名称只会在封闭的作用域中遮盖任何相似的名称。如果您了解语义,这不一定是一件坏事。如果您在假设封闭的
err
可以访问的情况下进行编码,则您将需要更改假设。
规格
生产Catch:catch(Identifier)块的评估如下:
令C为已传递给此生产的参数。
让oldEnv成为运行中的执行上下文的LexicalEnvironment。
让catchEnv为通过将oldEnv作为参数调用NewDeclarativeEnvironment的结果。
调用catchEnv的CreateMutableBinding具体方法,将Identifier String值作为参数传递。
调用catchEnv的SetMutableBinding具体方法,并以I,C和false作为参数。请注意,在这种情况下,最后一个参数无关紧要。
将正在运行的执行上下文的LexicalEnvironment设置为catchEnv。
令B为评估Block的结果。
将正在运行的执行上下文的LexicalEnvironment设置为oldEnv。
返回B。
注意无论控件如何离开“块”,词法环境始终会恢复为其以前的状态。
,检查以下答案:
JSLint抱怨我的尝试/捕获
如前所述,ѭ5打开一个新的块范围。参见https://developer.mozilla.org/en/JavaScript/Reference/Scope_Cheatsheet
确实,文档的顶部说明了它并不是全部标准,但是在ES5第12.14节中,有关执行“ 1”块的部分明确将MDC的描述定义为标准:
无论控制权如何离开LexicalEnvironment,始终将其恢复为以前的状态。
,如果以后需要引用该错误,则在顺序尝试中重用相同的参数名称可能会遇到问题。
如果调用了多个catch,则最后一个或函数作用域表达式的作用域将只有最后一个。
jsLint很保守-如果您可以防止使用唯一变量造成麻烦,为什么不使用它呢?