Function Declaration or Function Expression? A comparison

Aarón Sánchez
#NexuDev
Published in
6 min readAug 17, 2017

Why does JavaScript behave as it does? What is hoisting? Do I even know how to JavaScript?

Photo by https://goo.gl/K4feMF

Honestly, I hate JavaScript and at the same time I don’t. I have this ongoing tough love with it, but at the end, I always love it. I believe everyone can relate to this feeling.

What I’m trying to express is: C’mon, in one side you have OOP features and on the other side you syntactic-sugar as a functional programming language. What is not to like?

Yes, it is a mess, but I want to share some tips that helped me understand in a better way how does JavaScript works and clear some misconceptions.

Function Declaration

According to MDN web docs a Function Declaration has the following syntax:

function name([param,[, param,[..., param]]]) {
[statements]
}

So, there’s no big deal here. Anyone who knows how to program, knows how to declare a function, and it’s pretty much conventional. Notice that you start with the reserved word function as you’d normally do. Just as variable declarations must start with var, Function Declarations must begin with function.

A Function Declaration defines a named function variable without requiring variable assignment, and occurs as standalone constructs.

Function Expressions

Now, those who have programmed before in JS knows there’s another way to create functions. Here’s the syntax:

var myFunction = function [name]([param1[, param2[, ..., paramN]]]) {
statements
};

You can see that syntactically you just need to add a variable assignment at the beginning, and the function’s “name” is optional, giving us the chance of creating anonymous functions. On the other hand, if you do decide to name the function, the scope of the name will only be within the declared function (the reason of this is because JavaScript has a function-level scope).

Finally, a Function Expressions can be used as an IIFE (Immediately Invoked Function Expression) which runs as soon as it is defined. You can read more about IFFE on codeburst.io staff account ‘s story by @BrandonMorelli here.

Before comparing both approaches I want to give you some examples to make this more interesting.

Hands-On!

So, I’m going to show you some functions and the only thing you have to do is “guess” which value will return. Simple!

Photo by https://goo.gl/MVrpfy

Example №1.1.

function foo() {  // Function Expression
var bar = function() {
return 11;
};
return bar(); // Function Expression
var bar = function() {
return 8;
};
}
foo();

So, pretty straight forward, right?!

The returned value here is 11. If you don’t believe me, I invite you to open your JavaScript console and test the code.

Example №1.2.

For the second round we have:

function foo(){  // Function Declaration
function bar() {
return 11;
}
return bar(); // Function Declaration
function bar() {
return 8;
}
}
foo();

In this case, the returning value is 8.

If you’re like me and learned Java before JavaScript, maybe you’re a little baffled (the first time I saw this it didn’t make any sense for me). Perhaps you already know why this happens or have some idea. I’ll clarify everything later in the post, don’t worry.

Let’s look at some other examples and I’ll explain what the hell is going on.

Example №2.1.

function foo(){
return bar();

// Function Expression
var bar = function() {
return 11;
};

// Function Expression
var bar = function() {
return 8;
};
}
foo();

Wait! Don’t say any number. This time, try running the code first through the console.

As you may know now, this piece of code doesn’t work. It raises the following error:

Uncaught TypeError: bar is not a function

Let’s see the final example:

Example №2.2

function foo(){
return bar();
// Function Declaration
function bar() {
return 3;
};
}
foo();

The answer here is 3.

For me, it was a little confusing at first, but promise, is not that hard. The problem for me is that I wasn’t introduced to the concept of “hoisting”.

What is hoisting?

One of the biggest difference between Function Declarations and Function Expressions is that Function Declarations always get hoisted invisibly to the top of their containing scope by the JavaScript interpreter whereas in Function Expressions only the variable declaration part (var myFunction = …) gets hoisted, but their assignment expression does not.

According to w3schools.com:

Hoisting is JavaScript’s default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function).

Photo by https://goo.gl/MU7LXD

For example, the following code:

function foo() {
bar();
var x = 1;
}

is actually interpreted like this:

function foo() {
var x;
bar();
x = 1;
}

As you can see, the declaration was moved to the top of the function (due to function-level scope).

Here’s another example:

function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}

and this is how it is interpreted:

function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}

This is what makes Function Declarations behave differently! The declaration moves to the top of the block-scope.

Let’s analyze our previous exercises.

Solution №1.1

function foo() {
var bar = function() {
return 11;
};
return bar();
var bar = function() {
return 8;
};
} // 11

Gets interpreted as:

function foo() {
// variable declaration
var bar = undefined;
var bar = undefined;
// assignment expression
bar = function() {
return 11;
};
return bar();
// assignment expression
bar = function() {
return 8;
};
} // 11

It is making more sense, doesn’t it?

Solution №1.2

function foo(){
function bar() {
return 11;
}
return bar();
function bar() {
return 8;
}
} // 8

It may be interpreted a little more like this:

function foo(){
function bar() {
return 11;
}
// re-define the function
function bar() {
return 8;
}
return bar();
} // 8

See? The second function is hoisted and then re-defined, so the returning value is 8, as stated before.

And just for completeness, let’s analyze the last two examples:

Solution №2.1

function foo(){
var bar = undefined;
var bar = undefined;
return bar();
bar = function() {
return 11;
};
bar = function() {
return 8;
};
} //Error

That’s why the raised error stated that Uncaught TypeError: bar is not a function because it is not a function yet!.

Solution №2.2

It will be interpreted somehow like this:

function foo(){
function bar() {
return 3;
};
return bar();
}

And that is why in this exercise there’s no error.

You can read more about JavaScript’s secrets on the amazing article from Ben Cherry’s Adequately good decent programming advice blog.

Conclusion:

  • Declare your variables at the top! This way you’ll avoid any hoisting errors you may be overlooking.
  • Function Declarations are hoisted by the compiler.
  • The function name in Function Expressions is not visible outside of it’s scope.
  • The variable declaration part of the Function Expression gets hoisted, but their assignment expression does not.

--

--

Aarón Sánchez
#NexuDev

Proud member of #NexuDev, Computer Engineer, data-driven thinking enforcer.