Skip to content

Instantly share code, notes, and snippets.

@adammagana
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adammagana/44662b3082c48d25ac7a to your computer and use it in GitHub Desktop.
Save adammagana/44662b3082c48d25ac7a to your computer and use it in GitHub Desktop.

Question:

What is the difference between a function declaration function myVar() {} and a function expression var myVar = function() {};?

Answer:

In order to properly understand the (subtle) differences between a function declaration and a function expression we'll need to dive into the inner workings of JavaScript a little bit.

Consider this:

console.log(myVar); // ReferenceError: myVar is not defined

As expected, a ReferenceError is thrown as myVar is not defined. Now consider the following code block:

console.log(myVar); // undefined

var myVar = 'John likes ponies.';

console.log(myVar); // 'John likes ponies.'

Strangely the first console.log did not throw a ReferenceError as one might expect; it was undefined. This is because JavaScript has "hoisting." Hoisting basically looks ahead and hoists all of the variables to the top of scope. myVar was hoisted to the top of the scope because it was declared somewhere down the sequence. Here's what actually ended up happening despite the structure of our last code block:

var myVar;

console.log(myVar); // undefined

var myVar = 'John likes ponies.';

console.log(myVar); // 'John likes ponies.'

Knowing that let's look at how a function expression could be effected by hoisting:

console.log(myFunc()); // ReferenceError: myFunc is not defined

As expected myFunc() throws a ReferenceError just as myVar did in our first code block. But what happens when we leverage JavaScript hoisting by writing a function expression after our log statement?

console.log(myFunc()); // TypeError: undefined is not a function

var myFunc = function () {
    return 'John likes ponies';
};

Even though we have created a function expression to define myFunc AND myFunc effectively gets hoisted above our console.log statement the result of our log is still a TypeError. myFunc may be hoisted, however, its value is still undefined and it cannot be called as a function until after our function expression statement. With hoisting this is what our previous code block actually looks like:

var myFunc;

console.log(myFunc()); // TypeError: undefined is not a function

myFunc = function () {
    return 'John likes ponies';
};

However, function declarations behave differently because they also have hoisting. Declared functions are accessible anywhere within the function scope. This is a valid example:

console.log(myFunc()); // 'John likes ponies'

function myFunc() {
    return 'John likes ponies';
};

It's easy to see how relying on hoisting with function expressions and function declarations can be tricky, especially for someone newer to JavaScript. I avoid relying on hoisting using these two rules.

  1. All of my var statements go at the top of the scope. (with the exception of a var statement in a for loop initialization)
  2. All of my named functions are function declarations immediately after my var statements. (with the exception of the occasional anonymous callback function)

Enforcing these guidelines is useful for developers at all levels being that it better represents how the code is actually interpreted.

So how does a function expression differ from a function declaration? It all depends on context and use. Generally speaking you should follow a pattern that is as true to the runtime version of the code as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment