Functions First

Both function declarations and variable declarations are hoisted. But a subtle detail (that can show up in code with multiple “duplicate” declarations) is that functions are hoisted first, and then variables.

Consider:

  1. foo(); // 1
  2. var foo;
  3. function foo() {
  4. console.log( 1 );
  5. }
  6. foo = function() {
  7. console.log( 2 );
  8. };

1 is printed instead of 2! This snippet is interpreted by the Engine as:

  1. function foo() {
  2. console.log( 1 );
  3. }
  4. foo(); // 1
  5. foo = function() {
  6. console.log( 2 );
  7. };

Notice that var foo was the duplicate (and thus ignored) declaration, even though it came before the function foo()... declaration, because function declarations are hoisted before normal variables.

While multiple/duplicate var declarations are effectively ignored, subsequent function declarations do override previous ones.

  1. foo(); // 3
  2. function foo() {
  3. console.log( 1 );
  4. }
  5. var foo = function() {
  6. console.log( 2 );
  7. };
  8. function foo() {
  9. console.log( 3 );
  10. }

While this all may sound like nothing more than interesting academic trivia, it highlights the fact that duplicate definitions in the same scope are a really bad idea and will often lead to confusing results.

Function declarations that appear inside of normal blocks typically hoist to the enclosing scope, rather than being conditional as this code implies:

  1. foo(); // "b"
  2. var a = true;
  3. if (a) {
  4. function foo() { console.log( "a" ); }
  5. }
  6. else {
  7. function foo() { console.log( "b" ); }
  8. }

However, it’s important to note that this behavior is not reliable and is subject to change in future versions of JavaScript, so it’s probably best to avoid declaring functions in blocks.