First, if you run the code at jslint.com, you only get the redefinition error, which is valid. So I'm not sure why you're seeing errors 1 & 3. How are you linting? Is it within another app? What date of jslint.js are you using? etc etc
/*jslint sloppy:true, white:true, browser:true, devel:true */
(function () {
var i = 'a';
console.log(i);
function foo () {
var i = 'b';
console.log(i);
}
foo();
console.log(i);
foo();
}());
That gives me only...
Redefinition of 'i' from line 3.
var i = 'b';
Fair enough. Same deal from the pastie in your question's comments. As Jeremy says, the code won't break. It's just confusing. Why not use j
(or, of course, a descriptive var name in live code) in foo
or the anonymous function used in the pastie's each
?
When you use JSLint, it's important to keep in mind that Crockford believes, "It is difficult to write correct programs while using idioms that are hard to distinguish from obvious errors." Covering your outer i
with foo
's inner i
is confusing.
Imagine if foo
read...
function foo () {
console.log("Maybe I think I'm getting old 'i' here: " + i);
var i = 'b';
console.log(i);
}
JSLint (strangely, if you ask me) doesn't require that the var
statement be the first line in each scope, only that it occurs before you reference the variables.
So if you run your test code with that new foo
, you'll get undefined for foo
's i
before you hit the declaration statement b/c of variable hoisting. Bizarre, right? (Or expected, depending on your JS experience!)
a
Maybe I think I'm getting old 'i' here: undefined
b
a
Maybe I think I'm getting old 'i' here: undefined
b
You could argue that JSLint got that one wrong -- that it should have not only complained about the Redefinition
, but should have also complained that 'i' was used before it was defined.
within foo
's scope. I won't argue that. ;^)
I will say, however, that the redefinition is an idiom that's hard to distinguish from an obvious error. Best practice? Don't reuse variable names for different values in overlapping scopes.