Skip to content

breaking down the two different types of functions


<- return to blog

Which is better?

Arrow functions or function declarations?

In this article we are going to break down the two different types of functions.

Async Function Declaration

For example:

async function example() {
  // ...
}

This is an async function declaration.

Function declarations are hoisted, which means its definition is available throughout its scope. It is also a named function (its name is accessible within the function body for recursion and debugging).

Async Arrow Function Expression

For example:

const example = async () => {
  // ...
}

This is an async arrow function expression.

Function expressions are not hoisted, it’s assigned to a variable (example) and only available after the assignment.

Arrow functions have a lexically bound this and no own arguments object, among other differences from regular functions.

Which is better?

The Winner: Function Expressions

const example = async () => {
  // ...
}

✅ Why it's better (in modern JS):

Consistent scoping

Arrow functions don’t rebind this, arguments, or super. That makes them predictable in callbacks or component methods (like in Vue or React).

Immutable by default

Using const when necessary prevents reassignment — safer, less footguns.

Clear async intent

async keyword is directly visible at the function definition site. Readability wins.

Function expression > declaration (in modules)

Hoisting with function declarations (async function example() {}) can be misleading in modern module systems where temporal dead zone rules apply.

When function declarations win

Function declarations win over function expressions in JavaScript in terms of hoisting—they are fully hoisted to the top of their scope (i.e., available before they're defined in the code), while function expressions are not.

<- return to blog