Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

var keyword in try/catch expressions: JSLint bug or global assignment?

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?

like image 966
kojiro Avatar asked Nov 10 '11 14:11

kojiro


People also ask

What is var keyword in JavaScript?

var is the keyword that tells JavaScript you're declaring a variable. x is the name of that variable.

What is the scope of a variable declared with var keyword?

The scope of a variable declared with var is its current execution context and closures thereof, which is either the enclosing function and functions declared within it, or, for variables declared outside any function, global.

Should you use VAR in JS?

The Var Keyword This means that if a variable is defined in a loop or in an if statement it can be accessed outside the block and accidentally redefined leading to a buggy program. As a general rule, you should avoid using the var keyword.

Can let be a global variable?

let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope.


2 Answers

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

like image 120
Lee Kowalkowski Avatar answered Nov 15 '22 05:11

Lee Kowalkowski


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.

like image 41
BehradKhodayar Avatar answered Nov 15 '22 06:11

BehradKhodayar