The "Value of '{a}' may be overwritten in IE8 and earlier" error is thrown when
JSHint or ESLint encounters a try...catch
statement in which the catch
identifier is the same as a variable or function identifer. The error is only
raised when the identifer in question is declared in the same scope as the
catch
. In the following example we declare a variable, a
, and then use a
as the identifier in the catch
block:
var a = 1;
try {
b();
} catch (a) {}
JSLint will also raise an error in this situation but it uses the more generic "'{a}' is already defined" message.
This error is raised to highlight code that may not work as you expect in older browsers. In modern browsers you code will run without any problems but in Internet Explorer 8 and below you may end up with hard-to-trace bugs.
The ECMAScript 5 specification shows that the identifier of a catch
block
should be bound to a new declarative environment, created especially for the
catch
block, rather than that of the enclosing scope (ES5 12.14):
The production Catch:
catch (
Identifier)
Block is evaluated as follows:
- Let C be the parameter that has been passed to this production.
- Let oldEnv be the running execution context's LexicalEnvironment.
- Let catchEnv be the result of calling NewDeclarativeEnvironment passing oldEnv as the argument.
- Call the CreateMutableBinding concrete method of catchEnv passing the Identifier String value as the argument.
- Call the SetMutableBinding concrete method of catchEnv passing the Identifier, C and false as arguments. Note that the last argument is immaterial in this situation.
- Set the running execution context's LexicalEnvironment to catchEnv.
- Let B be the result of evaluating Block.
- Set the running execution context's LexicalEnvironment to oldEnv.
- Return B.
Effectively this says that a catch
block has its own lexical environment to
which its identifier is bound. When the catch
block has been executed the
running execution context's lexical environment is reset to the state it was in
before the catch
block. The running execution context is the scope in which
the catch
block occurs. This works as stated in all modern browsers but in
Internet Explorer 8 and below the identifer of the catch
block appears to be
bound to the running execution context's lexical environment rather than that of
the catch
block. The result is that an existing variable with the same
identifer will be overwritten with the value of the exception. For an excellent
in-depth analysis of this bug see The "catch" with try...catch by Ben
Alman.
To resolve this issue simply ensure your exception parameter has an identifier unique to its scope:
var a = 1;
try {
b();
} catch (e) {}
In JSHint 1.0.0 and above you have the ability to ignore any warning with a
special option syntax. The identifier of this
warning is W002. This means you can tell JSHint to not issue this warning
with the /*jshint -W002 */
directive.