Hello Sunil
differences-between-arrow-and-regular-functions-js

Top 7 Differences between arrow functions and regular functions in JavaScript – Must Read

In JavaScript, a function is a block of code designed to perform a particular task. Functions allow programmers can break up a large program into multiple smaller, more manageable components. As a result, there is no longer a need to write the same code repeatedly.

You can define JavaScript functions in many ways, two of them are: regular functions and arrow functions.

Regular Function in JavaScript

One of the basic way to define a function in JavaScript by using function keyword.

// function declaration
function greet(name) {
    return `Hey ${name}`
}
console.log('Sunil');  //Sunil

// function expression
const greet1 = function(name1) {
    return `Hey ${name1}`
}
console.log('Sunil');  //Sunil

You can call both function declaration and function expression as Regular Function in JavaScript.

Arrow Function in JavaScript

Arrow function was introduced in ES6. And it introduced a simple and shorter way to create functions.

const greet = (name) => {
    return `Hey ${name}`
}
console.log('Sunil');  //Sunil

While both the regular and arrow syntaxes define functions, when would you use one or another? That’s a good question.

Also Read: Arrow Functions in JavaScript

In this post, we will show you the difference between the two, so you could choose the right syntax for your needs.

Let’s discuss below πŸ‘‡

Difference 1: this value

Regular function and this value

Inside a regular JavaScript function, this value is dynamic.

The dynamic context means that the value of this depends on how the function is invoked. In JavaScript, there are 4 ways you can invoke a regular function.

  • 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.
//During a simple invocation the value of this equals 
//the global object (or undefined if the function runs in strict mode)

// 1️⃣ Simple Invocation
function simpleInvocation() {
    console.log(this);
}
simpleInvocation(); // Window Object


//During a method invocation the value of this is the 
//object owning the method

// 2️⃣ Method Invocation
const methodInvocation = {
  method() {
      console.log(this);
  }
};
methodInvocation.method(); 
// logs methodInvocation object

//During an indirect invocation using 
//myFunc.call(thisVal, arg1, ..., argN) or 
//myFunc.apply(thisVal, [arg1, ..., argN])
//the value of this equals to the first argument

// 3️⃣ Indirect Invocation
const myContext = { value: 'A' };
function myFunction() {
  console.log(this);
}

myFunction.call(myContext);  // logs { value: 'A' }
myFunction.apply(myContext); // logs { value: 'A' }


//During a constructor invocation using new keyword 
//this equals the newly created instance

// 4️⃣ Constructor Invocation
function constructorInvocation() {
    console.log(this);
}
new constructorInvocation(); 
// logs an instance of constructorInvocation

Arrow function and this value

Unlike regular functions, arrow functions don’t have their own this binding. If we access this in the arrow function it will return the this of the closest non-arrow parent function or in simpler term – it refers to its parent scope.

const user = {
	username: 'Sunil',
	getUserName: () => {
	  return this.username;
	  //here this refers to window object, 
	  //instead of user object
	},
};
const getName = user.getUserName;
console.log(getName()); //undefined 
console.log(user.getUserName()); //undefined

The value of this in the arrow function is determined at the time of declaration and never changes. So call, apply, bind cannot change the value of the arrow function this.

Let’s see one more example:

var name = "Ram"
let newObject = {
    name : "Hari",
    arrowFunc: () => {
        console.log(this.name); 
    },
    regularFunc() {
        console.log(this.name); 
    }   
}
newObject.arrowFunc(); // Ram
newObject.regularFunc(); // Hari

So, this inside an arrow function always refers to this from the outer context.

Difference 2: Constructors

Regular function and constructors

Regular functions are constructible, they can be called using the new keyword.

function add (x, y) {
    console.log(x + y)
}
let sum = new add(2,3); // 5

Arrow function and constructors

However, arrow function can never be used as constructor functions. Hence, they can never be invoked with the new keyword.

let add = (x, y) => console.log(x + y);
const sum = new add(2,4); 
// TypeError: add is not a constructor

Difference 3: Arguments object

Regular function and Arguments object

In regular function, Arguments keywords can be used to access the arguments of which passed to function.

function regularFunction(a,b) {
    console.log(arguments)
}
regularFunction(1,2)
// Arguments[1,2]

Arrow function and Arguments object

Arrow function do not have an arguments binding.

const arrowFunction = (a,b) => {
    console.log(arguments)
}
arrowFunction(1,2)
//ReferenceError: arguments is not defined

However, if you want to access arguments in an arrow function, you can use the rest operator.

var arrowFunction = (...args) => {
    console.log(...args)
}
arrowFunction(1,2) // 1 2

Difference 4: Implicit return

Regular function and Implicit return

In regular function, you have to use return keyword to return any value. If you don’t return anything then the function will return undefined.

//return keyword used
function myFunction() {
  return 42;
}

console.log(myFunction()); // => 42

//return keyword missing 
function myEmptyFunction() {
  42;
}
console.log(myEmptyFunction());  // => undefined

function myEmptyFunction2() {
  42;
  return;
}

console.log(myEmptyFunction2());  // => undefined

Arrow function and Implicit return

Arrow functions behave in the same way when returning values.

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

const increment = (num) => num + 1;
increment(41); // => 42

console.log(increment(41));  // => 42

increment() consists of only one expression: num + 1. This expression is implicitly returned by the arrow function without the use of return keyword.

Difference 5: Methods

Regular function and Methods

Regular functions are the usual way to define methods on classes or objects.

In the following class Hero, the method logName() is defined using a regular function:

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

  logName() {
    console.log(this.heroName);
  }
}

const batman = new Hero('Batman');
batman.logName(); //Batman

Usually, regular functions as methods are the way to go.

Sometimes you would need to supply the method as a callback, for example to setTimeout() or an event listener. In such cases, you might encounter difficulties accessing this value.

For example, let’s use logName() method as a callback to setTimeout():

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

  logName() {
    console.log(this.heroName);
  }
}

const batman = new Hero('Batman');
batman.logName(); //Batman
setTimeout(batman.logName, 1000); // after 1 second logs "undefined"

After 1 second, undefined is logged to console. setTimeout() performs a simple invocation of logName (where this is the global object). That’s when the method is separated from the object.

Let’s bind this value manually to the right context:

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

  logName() {
    console.log(this.heroName);
  }
}

const batman = new Hero('Batman');
batman.logName(); //Batman
setTimeout(batman.logName.bind(batman), 1000); // after 1 second logs "Batman"

batman.logName.bind(batman) binds this value to batman instance. Now you are sure that the method doesn’t lose the context.

Also Read: Understanding – Call, Apply, Bind

Binding this manually requires boilerplate code, especially if you have lots of methods. There’s a better way: the arrow functions as a class field.

Arrow function and Methods

Thanks to the class fields feature you can use the arrow function as methods inside classes.

Now, in contrast with regular functions, the method defined using an arrow binds this lexically to the class instance.

Let’s use the arrow function as a field:

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

 logName = () => {
    console.log(this.heroName);
  }
}

const batman = new Hero('Batman');
batman.logName(); //Batman

Now you can use batman.logName as a callback without manual binding of this. The value of this inside logName() method is always the class instance:

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

 logName = () => {
    console.log(this.heroName);
  }
}

const batman = new Hero('Batman');
batman.logName(); //Batman
setTimeout(batman.logName, 1000); // after 1 second logs "Batman"

Difference 6: No duplicate named parameters

In normal function, we can do this:

// βœ… will work 
function add(a, a) {}
// ❌ will not work 
'use strict';
function add(a, a) {}
// Uncaught SyntaxError: Duplicate parameter name not allowed in this context

Arrow functions can never have duplicate named parameters, whether in strict or non-strict mode.

const arrowFunc = (a,a) => {}
// Uncaught SyntaxError: Duplicate parameter name not allowed in this context

Difference 7: Function Hoisting

Regular function and Function Hoisting

In regular function, function gets hoisting at top.

console.log(normalFunc());  //Normal Function
function normalFunc() {
    return "Normal Function"
}
console.log(normalFunc()); //Normal Function

Arrow function and Function Hoisting

In arrow function, function get hoisted where you define. So, if you call the function before initialization you will get ReferenceError.

console.log(arrowFunc());
// ReferenceError: Cannot access 'arrowFunc' before initialization
const arrowFunc = () => {
    return "Arrow Function"
}

Conclusion

Understanding the differences between regular and arrow functions helps choose the right syntax for specific needs.

What other differences between the arrow and regular functions do you know?

Thanks for reading the article ❀️

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there πŸ‘‹ I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there πŸ‘‹ I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.