I'm trying to understand why I'm getting the following error, not how to work around it.
Passing the following code to JSLint or JSHint yields the error '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) { }
}
The obvious assumption here is that catch
behaves, or should behave, like a function. Thus, err
is neither a global variable, nor a local variable to xyzzy
, but a parameter for the catch
block.
In browsing the ECMA-262 Standard, section 12.14 describing The try
Statement indicates that the catch
clause takes an Identifier that is bound to an exception. Additionally the semantic production rule for catch
refers to a parameter that's passed calling out Identifier as an argument.
This seems to suggest to the casual reader that the above code is valid and that perhaps the lint tools have a bug.
Even IntelliJ's strictest JavaScript code inspection analysis doesn't report there being a problem with err
being redefined.
More of a concern, if it is a variable scoping concern, then one might surmise that the err
is bleeding into the global space, which poses a whole host of other problems, and that instead one should declare it up front, like this:
/*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) { }
}
But this only results now in two errors about err
at each of the catch statements, making the problem worse and potentially introducing variable shadowing.
The lint tools are suggesting that each catch
block introduces not just it's own lexical scope, but a new variable as well. This can't be right.
Simply making err1
, err2
, ... to placate the static analysis tools merely hides the symptom and doesn't contribute to cleaner code.
JavaScript Gurus: Is this a bug in the lint tool, a dark corner with the JavaScript spec, or a fundamental misunderstanding of what's happening here?
UPDATE: Wrote to Douglas Crockford, author of JSLint, and it turns out there's a very valid reason for this warning. See answer below.