Hoisting and Scope

I answered a question on stackoverflow.com today that I can remember struggling with when I first started with javascript. It had to do with hoisting and scope.

Hoisting is a by-product of the functional scope of javascript. Variables and functions declared within a function are in scope throughout the function, even before they are initialized. That makes for situations like the following:

// this: 
function foo() {
    console.log(x);
    var x = 1;
}

//is actually interpreted like this:
function foo() {
    var x;
    console.log(x);// undefined
    x = 1;
}

In a browser, all that business is within the window scope.

If we start to add some higher level variables into the script, it starts to get even more confusing:

(function parent() {
  // x declared and assigned in parent scope
  var x = 2;

  function foo() {
      console.log(x); // 2 (closed around parent scope)
  }

  function bar() {
      console.log(x); // undefined (bar scope, x declaration is hoisted, but not defined yet)
      var x = 1;
  }
  function baz() {
      var x = 3;
      console.log(x); // 3 (baz scope, defined)
  }
  //run 
  foo();
  bar();
  baz();
}());

Because of these interesting scope quirks, many javascript devs, including myself, declare variables at the top of their scope. This convention is strange looking to coders used to block scope languages, where it is suggested that one declare variables close to where they are used.