DEV Community

Schemetastic (Rodrigo)
Schemetastic (Rodrigo) Subscriber

Posted on • Edited on

When to use Function declarations or Function expressions in JavaScript?

What are function declarations and function expressions?

Basically you can define functions with the function keyword at least in two ways:

with a Function declaration which starts with the function keyword, then the name of the function, then the arguments (), and finally the statements{}; Also as a Function expression which can be stored in a variable, a constant or passed through a function argument, the syntax is quite similar to a function declaration, however, a function expression can be anonymous or be named.

Here's an example of a function declaration:

function toggleSwitch(/*arguments*/){
    // statements
}
Enter fullscreen mode Exit fullscreen mode

An anonymous function expression:

const toggleSwitch = function(/*arguments*/){
    // statements
}
Enter fullscreen mode Exit fullscreen mode

A named function expression:

const toggleSwitch = function switch(/*arguments*/){
    // statements
}

Enter fullscreen mode Exit fullscreen mode

You could call all of those functions in the same way, with toggleSwitch(). So... what's the difference? Can I just use the one that looks prettier? Although it might seems like that, there are actual differences in the way they operate in your code, once you know them is easier to know which to use. Let's dig into it!

Differences between each type of function

Hoisting

Function declarations are available in it's scope from up to down in your code, but a function expression can't be called unless it has already been declared. This means that you can refer to a function declaration even before it has been declared, but not in a function expression. For example:

This one works and the content is logged:

callMeMaybe();

function callMeMaybe(){
    console.log("here's my number 😏");
}
Enter fullscreen mode Exit fullscreen mode

This one would throw an error:

callMeMaybe();
// ReferenceError: Cannot access 'callMeMaybe' before initialization

const callMeMaybe = function(){
    console.log("Where you think you're going, baby?");
}

// Credit: Carly Rae Jepsen
Enter fullscreen mode Exit fullscreen mode

So if for some reason you need to have access to functions on your code before they've been declared (perhaps to avoid obfuscation of other core functions, or to improve understanding of your code to others), then knowing this becomes handy.

With const and let variables you can create block-scoped functions easily

constants and let variables are block-scoped. constants can only be defined once, and let variables even though they can be redefined, they can't be redefined twice with the let declaration unlike var statements. Same happens if you use them to define functions. For example:

This one throws a SyntaxError cause you can't have two constants with the same name:

const hello = function(){
    console.log("Hello");
}

// SyntaxError: Identifier 'hello' has already been declared
const hello = function(){
    console.log("is it me you're looking for?");
}

hello();

// Credit: Lionel Richie
Enter fullscreen mode Exit fullscreen mode

But you can redefine a Function Declaration:

function hello(){
    console.log("Hello, it's me");
}

function hello(){
    console.log("Hello from the other siiide!");
}

hello();
// logs: "Hello from the other siiide!"

// Credit: Adele
Enter fullscreen mode Exit fullscreen mode

This is useful if you need to block the scope of your functions to avoid their overriding from other sources and get unexpected behaviors. Also this can make debugging easier.

Other things to take in account

  • With variables you can make an object of functions (or methods) using the object definition syntax ({}), which could lead to more organized code. You could also add methods to a function declaration like this myFunction.someMethod = ..., however this was more of a consideration back in the old days, nowadays you could use classes which provide a nicer syntax. Still... there are notable differences I would say.
  • Since function expressions can be anonymous, this might lead to confusion when that function has an error, but if you name them you can get more specificity in a stack trace. However this could become more obvious when you define a function expression outside of a variable, like in a promise chain.

Which approach should I use?

As many things in life, it depends, each project is different and there are tons of ways to achieve the same thing.

In my personal opinion, I would generally use function declarations cause I think they provide an easier readability. Having the word "function" at the start of a line makes it easier to know that you are defining a function than having "const" or "let" at the start of a line, it's also nice to know I can use them anywhere I want in their current scope. But in general I would rather use function expressions inside function declarations cause inside a function I would normally define variables to complement what the function actually does. But again, it depends, how do you think it best suits your needs?

At the end of the day I would say it depends a lot on you, the people and the project you are working on. So hopefully this article has given you useful insights about JavaScript functions.

Some useful references that were used for this article:

Note: None person or website mentioned in this article is sponsoring this content

Until the next time!

I'll upload the next part of this series next Tuesday, October 11th. If you liked this one, stick with me!

Did I missed anything? I'm pretty sure there is a lot more to say about this, feel welcome to write your comments below!

Top comments (5)

Collapse
 
poetryofcode profile image
Poetry Of Code

I always confuse those 2 terms.
Do I understand correctly, an expression we assign to a variable (we get value) but a declaration we do not get value?

Collapse
 
schemetastic profile image
Schemetastic (Rodrigo) • Edited

Interesting question, a declaration is made with the keyword function and they are not dependent of a variable, and they aren't anonymous, they are available in their scope. A function expression goes beyond being defined in a variable, for example, a function expression could be passed in a function argument, for example... getData(function(){/*This is a callback*/}).

Collapse
 
poetryofcode profile image
Poetry Of Code

Awesome. Thanks

Collapse
 
fruntend profile image
fruntend

Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 🫰

Collapse
 
schemetastic profile image
Schemetastic (Rodrigo)

Hello! 😄

Thanks a lot for taking the time to feature me in your post, I'm glad you liked this article, I've been spending many hours writing the articles of this series.