12

JSLint does not like this code saying "'b' was used before it was defined"

var a = function () {
        b();
    },

    b = function () {
        alert("Hello, world!");
    };

a();   

but perfectly happy with this

var a, b;

a = function () {
    b();
};

b = function () {
    alert("Hello, world!");
};

a();   

But I am not defining anything in my second code snippet. I am merely declaring variable b.

So why is JSLint doing this? Is there a reason I should be declaring all my functions first?

PS I understand I could have just changed order of a and b, but in real project my functions are event handlers and sometimes they call each other, so it is probably not possible.

Evgeny
  • 6,261
  • 8
  • 35
  • 43
  • 1
    `a` references `b` before `b` exists (as JavaScript executes left-to-right), declare `b` before `a` and this will disappear. – Paul S. Oct 18 '12 at 20:35
  • 1
    @shhac `b` actually does exist since it was declared before it was referenced. It was simply undefined. – Micah Henning Oct 18 '12 at 20:59

3 Answers3

12

If your code is well-written and object-oriented, it is possible to declare your functions before they are used. But JSLint sets a lot of standards that really have little relevance to the functionality of your application, and I really doubt there are any performance implications declaring functions one way or the other.

Micah Henning
  • 2,125
  • 1
  • 18
  • 26
11

So why is JSLint doing this? Is there a reason I should be declaring all my functions first?

Yes, otherwise there might be some unexpected errors. Your code works because of JavaScript's "Hoisting". This mechanism pulls up all declarations, implicit or explicit and can cause some unexpected results.

Consider this code:

var s = "hello";    // global variable
function foo() {
    document.write(s);   // writes "undefined" - not "hello"
    var s = "test";      // initialize 's'
    document.write(s);   // writes "test"
};
foo();

It's being interpreted as follows:

var s = "hello";    // global variable
function foo() {
    var s;               // Hoisting of s, the globally defined s gets hidden
    document.write(s);   // writes "undefined" - now you see why
    s = "test";          // assignment
    document.write(s);   // writes "test"
}
foo();

(example taken from the german Wikipedia page: http://de.wikipedia.org/wiki/Hoisting)

user654123
  • 465
  • 6
  • 19
  • Main feature about Code 1 is that declaring var s anywhere inside a function arranges hoisting for the whole scope of it. Never mind that it is declared in the second line and called in the first - the variable is already hoisted. – Zon Jan 11 '16 at 10:48
  • Is hoisting actually relevant to the OP's first code block? The `a()` function is not called until after `b()` is defined. Does the JS engine (not JSLint) actually care whether the variable `b` referenced inside the first function exists at all at the time of declaration? I don't think it does as long as the syntax is ok. If it didn't exist when the function is called then you'd get a runtime error. – nnnnnn Feb 02 '16 at 11:18
3

In C it is what we call forward declaration, looks like it could be the same in JSLint. JSLint is aware of b and at that point b could be a function for all it cares (but if it isn't a function, it would throw an error of course)

Lews Therin
  • 10,907
  • 4
  • 48
  • 72
  • 1
    It has nothing to the *interpreter* or *js*, it's just how jjsLint checks things. – gdoron Oct 18 '12 at 20:30
  • 7
    JSLint is just code quality tool that is designed to hurt your feelings. Actually this code runs perfectly well. – Evgeny Oct 18 '12 at 20:32