9

I noticed an interesting result from JSLint while researching a codereview question. JSLint complained that a variable was used before it was defined. Here is a shortened version of code that produces the same result:

(function () {
    try {
        var a = 0;
        throw { name: "fakeError" };
    } catch (e) {
        a = 1;
    }
}());

My understanding of JavaScript says that the above code should be equivalent to:

(function () {
    var a;
    try {
        a = 0;
        throw { name: "fakeError" };
    } catch (e) {
        a = 1;
    }
}());

and indeed, neither example causes a to exist in the global scope when run through Firebug. I took a look at section 12.14 of the ECMA-262 spec, but I don't see anything that would lead me to think the functions should be treated differently. Is this just a bug in JSLint, or are the two expressions different in some functional way?

Community
  • 1
  • 1
kojiro
  • 74,557
  • 19
  • 143
  • 201

2 Answers2

5

It's just a bug, but JSLint's default options would prefer it if you moved all your var statements to the top anyway.

Lee Kowalkowski
  • 11,591
  • 3
  • 40
  • 46
1

While enclosing some block of code in curly braces {...} merely doesn't create a new scope in javascript, catch is an exception as noted in ECMAScript 5 spec. The code inside catch block has a different scope in comparison to the code outside. its treated like functions inner scope.

In other words, as noted here:

The catch block is unique in that JavaScript creates this identifier when the catch block is entered and it adds it to the current scope; the identifier lasts only for the duration of the catch block; after the catch block finishes executing, the identifier is no longer available.

function f() {
  try {
    throw "foo";
  } catch (e) {
  }
  // e undefined here
}

And as you know, one cannot expect variable hoisting from 2 different scopes of code in javascript. So, JSLint complains because he/she ;-) knows this.

behkod
  • 2,647
  • 2
  • 18
  • 33