Domanda

When running the following Javascript code through JSLint:

    (function () {
        var i = 'a';

        console.log(i);

        function foo () {
            var i = 'b';
            console.log(i);
        }

        foo();

        console.log(i);

        foo();
    }());

I get the following errors in JSLint:

    #1 Redefinition of 'i' from line 4.
       var i = 'b'; // Line 7, Pos 13
    #2 Unused 'i'.
       var i = 'a'; // Line 4, Pos 9
    #3 Unused 'foo'.
        function foo () { // Line 6, Pos 14

My questions:

  1. Why does it say foo() is unused when I am clearly calling it?

  2. Why does it say the function-scoped var i = 'b' is a redefinition of the one above it

  3. Why does it say that the first var i = 'a' definition goes unused?

È stato utile?

Soluzione 2

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.

Altri suggerimenti

You are getting the redefinition of i because it exists in both scopes.

This isn't really a problem, per se, however it is one thing that Crockford believes can cause confusing, so his tool catches it.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top