Saturday June 28, 2014:

Function Declarations vs. Function Expressions

What does this evaluate to?

var alpha = 1;  
var beta = function () {  
  if (!alpha) {
    var alpha = 2;
  }
  alert(alpha);
};
beta();  

It's 2! But why? Why not 1?

This is what's really happening:

var alpha;      // L1  
alpha = 1;  
var beta;  
beta = function () {  
  var alpha;    // Here's the money
  if (!alpha) {
    alpha = 2;
  }
  alert(alpha);
};

When JavaScript runs, the variable definitions are "hoisted" to the top, and set as undefined. That means at L1 the result of console.log(alpha); would be undefined. After this, values are assigned to the defined variables.

However, inside the beta function, a new scope is created where alpha is being defined again. Therefore, it's hoisted up to the top of the function and redefined as undefined.

The concept of hoisting is a large distinguishing factor between function declarations and function expressions.

Function Expressions

Here's an example:

var iExpress = function (str) {  
  alert( 'I\'m expressing that I ' + str );
};

As the above JavaScript is being compiled, here is what's going on:

var iExpress;  
iExpress = function (str) {  
  console.log( 'I\'m expressing that I ' + str );
};

Based on the above, what will the code below evaluate to?

var sayHello;  
console.log(sayHello());  
sayHello = function () {  
  console.log('Whattt upppppp!');
};

If you said Reference Error: sayHello is not defined then you're correct!

This is because the definition of the function hasn't been set yet.

Function Declarations

Now here's where functions get superpowers:

iDeclare('above');  
function iDeclare (str) {  
  console.log( 'I say...I decaaarrrre ' + str );
}
iDeclare('below');  

The code above, surprisingly, does not pump out a Reference Error.

    I say...I decaaarrrre above
    I say...I decaaarrrre below

When functions declarations are defined, they are parsed and evaluated before any other expressions. Even if declaration is positioned last in a source, it will be evaluated foremost any other expressions contained in a scope.

Cool right!?

Which one is better?

Well that's up to you. Some programmers enjoy defining their functions on top and invoking them below, and others like invoking their functions on top and defining them below. Here are some negatives for each:

Functional Declarations

  • Can be confusing because the order of their definition and invocation is flexible
  • You shouldn't use them in non-function blocks like if, while, and for
    • Some browsers will be okay with it, but it's not a good practice

Functional Expressions

  • Enforces definition and invocation order
  • Not automatically hoisted to the top