Arrow Functions vs. Regular Functions in JavaScript

Learn when and when not to use the arrow function

Chameera Dulanga
Bits and Pieces

--

Today, there are two common methods of declaring a function in JavaScript: Arrow functions and Regular functions. On most occasions, we use both these functions without considering their suitability or differences.

However, these functions differ in many significant ways, and we can’t replace one with another.

So in this article, I will explore 5 of these key differences in detail.

1. “this” Keyword

this keyword is one of the most used keywords in JavaScript. But when it comes to regular functions and arrow functions, it behaves in entirely different ways.

In regular function, this changes according to the way that function is invoked.

  • Simple Invocation: this equals the global object or maybe undefined if you are using strict mode.
  • Method Invocation: this equals the object that owns the method.
  • Indirect Invocation: this equals the first argument.
  • Constructor Invocation: this equals the newly created instance.
// Simple Invocation
function simpleInvocation() {
console.log(this);
}
simpleInvocatoin(); // logs global object
--------------------------------------------------------------------// Method Invocation
const methodInvocation= {
method() {
console.log(this);
}
};
methodInvocation.method(); // logs methodInvocation object
--------------------------------------------------------------------// Indirect Invocation
const context = { value1: 'A', value2: 'B' };
function indirectInvocation() {
console.log(this);
}
indirectInvocation.call(context); // logs { value1: 'A' }
indirectInvocation.apply(context); // logs { value1: 'A' }
--------------------------------------------------------------------// Constructor Invocation
function constructorInvocation() {
console.log(this);
}

new constructorInvocation(); // logs an instance of constructorInvocation

But, in the arrow functions, the behavior of this changes completely.

Arrow functions don't have their own “this”, and they don’t redefine the value of “this ”within the function.

Regardless of how you execute arrow functions, this inside an arrow function always refers to this from the outer context. This means that this keyword is lexically bound in arrow functions.

To understand it better, let’s consider the above example of Method Invocation with an arrow function to see the difference:

var variable = “Global Level Variable”;let myObject = {  variable: “Object Level Variable”, arrowFunction:() => { 
console.log(this.variable);
},
regularFunction(){
console.log(this.variable);
}
};
myObject.arrowFunction();
myObject.regularFunction();

This behavior of arrow functions makes them really useful when using callbacks inside methods.

You don't need to use workarounds like const self = this or callback.bind(this) with arrow functions, and it prevents any mistakes that can be caused by the use of this within callbacks.

2. Arguments Object.

In regular JavaScript functions, arguments keywords can be used to access the passed arguments when the function is invoked.

For example, If I call a function with 3 arguments, I will be able to access them using arguments keyword like this:

function exampleFunction() {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
exampleFunction(1,2,3)

But, arrow functions do not have their own arguments and it uses the arguments from the outer function.

The behavior of the arguments keyword within an arrow function is similar to the behavior of this keyword we discussed earlier, and it is resolved lexically.

let exampleFunction = {
printArguments : () => {
console.log(arguments);
}
}
exampleFunction.printArguments(1,2,3)

However, if you want to access arguments directly in an arrow function, you can use the rest parameters feature:

let exampleFunction = {
printArguments : (…args) => {
console.log(…args);
}
}
exampleFunction.printArguments(1,2,3);

3. Constructors / “new” keyword

As well know, we can easily construct objects with regular functions. We just need to invoke the function with the new keyword.

function Article(topic) {
this.topic= topic;
}

const article= new Article('JavaScript');

However, arrow functions can not be used as constructors.

Since this keyword is resolved lexically in arrow functions, we cant use it to construct objects.

4. Implicit return

In regular functions, we can use the return keyword to return any value from a function. If we don’t return anything, the function will implicitly return undefined.

function exampleFunction() {
return 10;
}
exampleFunction(); // output -> 10
--------------------------------------------------------------------function exampleFunction() {
var number = 10;
}
exampleFunction(); // output -> undefined
--------------------------------------------------------------------function exampleFunction() {
var number = 10;
return;
}
exampleFunction(); // output -> undefined

Arrow functions behave in the same way when returning values. But there is one advantage you can take from it.

If the arrow function contains one expression, you can omit the curly braces, and then the expression will be implicitly returned.

const addOne = (number) => number + 1;
addOne(10);

Final Thoughts

In this article, I have discussed some significant differences between regular functions and arrow functions in JavaScript. Based on the results and advantages, you might feel that arrow functions are better than regular functions.

But, that’s not true for all cases, and there are some situations you should avoid using arrow functions.

It is recommended to use regular functions when dealing with Promises, Callback functions with dynamic context, and Object methods.

So, as a developer, you should understand these differences to identify the best matching function type for your requirement.

Thank you for reading !!!

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--