Avoid this variable initialization pitfall

There's a few different ways we can write functions in Javascript.

First, there is the function declaration:

function declaredFunction() {
  // ...

Then there is a function expression that is referenced by a variable:

var functionExpression = function() {
  // ...

This largely seems like the same thing, but what's happening under the hood is a bit more nuanced:

In the first example, the function declaration is hoisted to the top of the executing function scope; This means both the variable declaredFunction and the function body is defined before the containing function executes. (Note: in this example, we don't have a containing function so the hoisting would happen whenever the program executes.)

In the second example, only the variable declaration functionExpression is hoisted to the top of the executing function scope. This means functionExpression has a value of undefined when the program begins execution, and it is only when the runtime gets to the line with the = where functionExpression is assigned a value that the variable functionExpression actually points to a value.

The second is how, I think, most people understand these 2 seemingly identical programs to execute. Here's an exercise to help further clarify the difference:

What are the values logged by the two examples below?


function declaration() {
  // ...

var expression = function() {
  // ...

In the first example, it's the entire function function declaration() {...} but in the second example, it's undefined.

Again, the function declaration is hoisted to the top of the executing function scope before the runtime begins execution. This means the variable declaration is defined and assigned a value before program execution.

The variable expression in the second example is hoisted to the top, but its assignment happens when the runtime gets to the assignment operator ( =)  during execution. Hence, the console.log(expression) is undefined.

Alternatively, if you use const instead of var, the runtime will give you an Uncaught ReferenceError: Cannot access 'expression' before initialization.

I guess it's just another case of why we should use const and let instead of var; It has better, more predictable runtime behavior.