DEV Community

loading...
Cover image for Regular vs Arrow Function

Regular vs Arrow Function

Suprabha
πŸ”₯ New JS, CSS, HTML articles every week πŸ”₯ Frontend engineer @gojekindonesia πŸ‘©πŸ»β€πŸ’» http://instagram.com/suprabhasupi
・5 min read

Define your functions in many ways.

One way is using function keyword:

// function declaration
function test(msg) {
    return `Hey ${msg}`
}

// function expression
const test = function(msg) {
    return `Hey ${msg}`
}
Enter fullscreen mode Exit fullscreen mode

You can call both function declaration and expression as Normal/Regular Function

Arrow function is introduced in ES6 and also known as fat arrow function.

const arrowFunction = (msg) => {
    return `Hey ${msg}`
}
Enter fullscreen mode Exit fullscreen mode

As you see both functions work same by above example. Now the question comes why do we need regular or arrow function.

Let's discuss below πŸ‘‡

1. Syntax

2. Arguments binding

3. this

4. new keyword

5. No duplicate named parameters

6. Function Hoisting

7. Methods

1️⃣ Syntax

We can write normal and arrow function in this way 😎

// ES5
var add = function(x, y) {
    return x + y
};

// ES6
let add = (x, y) =>  x + y 
Enter fullscreen mode Exit fullscreen mode

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.

function regFunc() {
    return "Regular Function";
}
regFunc(); 
// Regular Function

function regFunc() {
    console.log("Regular Function")
}
regFunc(); 
// Regular Function
// undefined
Enter fullscreen mode Exit fullscreen mode

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.

{} not required if its only one line of statement

const addOne = (number) => number + 1;
addOne(10);
Enter fullscreen mode Exit fullscreen mode

() not required if you pass only one argument

let add = x => x + x;
Enter fullscreen mode Exit fullscreen mode

If there is no arguments

let arrowFunc = _ => console.log("Arrow Function");
Enter fullscreen mode Exit fullscreen mode

2️⃣ Arguments binding

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

Example:

function regularFunction(a,b) {
    console.log(arguments)
}

regularFunction(1,2)
// Arguments[1,2]
Enter fullscreen mode Exit fullscreen mode

Arrow functions do not have an arguments binding.

const arrowFunction = (a,b) => {
    console.log(arguments)
}

arrowFunction(1,2)
//ReferenceError: argumnets is not defined
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

3️⃣ this

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.
// 1️⃣ Simple Invocation
function simpleInvocation() {
    console.log(this);
}

simpleInvocation(); 
// Window Object


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

methodInvocation.method(); 
// logs methodInvocation object


// 3️⃣ Indirect Invocation
const context = { aVal: 'A', bVal: 'B' };
function indirectInvocation() {
    console.log(this);
}

indirectInvocation.call(context);  // logs { aVal: 'A' }
indirectInvocation.apply(context); // logs { bVal: 'A' }


// 4️⃣ Constructor Invocation
function constructorInvocation() {
    console.log(this);
}

new constructorInvocation(); 
// logs an instance of constructorInvocation
Enter fullscreen mode Exit fullscreen mode

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

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

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

newObject.arrowFunc(); // Suprabha
newObject.regularFunc(); // supi
Enter fullscreen mode Exit fullscreen mode

4️⃣ new

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
Enter fullscreen mode Exit fullscreen mode

However, arrow functions 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
Enter fullscreen mode Exit fullscreen mode

5️⃣ 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

6️⃣ Function Hoisting

In regular function, function gets hoisting at top.

normalFunc()

function normalFunc() {
    return "Normal Function"
}

// "Normal Function"
Enter fullscreen mode Exit fullscreen mode

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

arrowFunc()

const arrowFunc = () => {
    return "Arrow Function"
}

// ReferenceError: Cannot access 'arrowFunc' before initialization
Enter fullscreen mode Exit fullscreen mode

7️⃣ Methods

You can define methods in class using regular function.

class FullName {
    constructor(name) {
        this.name = name;
    }

    result() {
        console.log(this.name)
    }
}

let name = new FullName("Suprabha")

console.log(name) 
// FullNameΒ {name: "Suprabha"}
Enter fullscreen mode Exit fullscreen mode

You need to apply method as callback also.

setTimeout(name.result, 2000) 
// after 1 second logs ""
Enter fullscreen mode Exit fullscreen mode

But if you bind this

setTimeout(name.result.bind(name), 2000) 
// Suprabha
Enter fullscreen mode Exit fullscreen mode

By above example, you can see that you have to bind the this to there context.

In arrow function, you don't have to bind with context.

class FullName {
    constructor(name) {
        this.name = name;
    }

    result = () => {
        console.log(this.name)
    }
}

let name = new FullName("Suprabha")

setTimeout(name.result, 2000) // Suprabha
Enter fullscreen mode Exit fullscreen mode

When not to use Arrow function πŸ‘©πŸ»β€πŸ’»

Object Methods

let dog = {
    count: 3,
    jumps: () => {
        this.count++
    }
}
Enter fullscreen mode Exit fullscreen mode

When you call dog.jumps, the number of count does not increase. It is because this is not bound to anything, and will inherit the value of this from its parent scope.

Reference 🧐

Summary

In regular function, this value is dynamic, In arrow function it equals to this of the outer function.

In regular function, arguments will give you list of parameter passed in function, In arrow function arguments is not defined.

In regular function, you always have to return any value, but in Arrow function you can skip return keyword and write in single line.

In arrow function parameters should be unique.

Hoisting matters in arrow function as function get not be invoked before initialisations.



Thanks for reading the article ❀️

Buy Me A Coffee

🌟 Twitter πŸ“š Ebooks 🌟 Instagram

Discussion (4)

Collapse
aplusdesigners profile image
Lee Baldwin

As a newbie to front-end development, I am trying to understand why developers would want to use arrow functions. It seems to me that it would just be easier to type the word function and return than to type an arrow function, unless they create a arrow function key on keyboards.

Collapse
isaacdlyman profile image
Isaac Lyman

Note that => is written with an equal sign and a greater-than sign, both common programming symbols and pretty accessibly on a standard keyboard.

As for why, the top reasons I use arrow functions are:
1) Succinctness. If I'm trying to add 1 to each element in listOfNumbers, the old way to do it was:

var incrementedNumbers = listOfNumbers.map(function (num) { return num + 1; }); 
Enter fullscreen mode Exit fullscreen mode

With an arrow function I can do

var incrementedNumbers = listOfNumbers.map(num => num + 1);
Enter fullscreen mode Exit fullscreen mode

Which is quicker to write and quicker to read.

2) Lexical context. When you write function, it creates its own this binding (that is, inside of a classic function, the this keyword refers to the function itself). But for arrow functions, this refers to the same thing both inside and outside the function; arrow functions don't create a lexical context. This is occasionally handy when I have some data in this that I need to use throughout a function, including in various predicates (like in functions passed to Array.map or async callbacks).

Collapse
manuthecoder profile image
Manu

Haha, I have an obsession with arrow functions
(I don't really care about IE, it's shutting down anyways someday)

Collapse
peerreynders profile image
peerreynders

MDN: Arrow function expressions:

An arrow function expression is a compact alternative to a traditional function expression, but is limited and can't be used in all situations.

i.e. preferring arrow functions you may be called upon to demonstrate knowledge of when not to use them, e.g. as class methods.

Plain ol' function is still the most appropriate for the general use case (and function hoisting can be quite helpful - you can put functions at the end of the script, out of the way of the primary script). Arrow functions were largely introduced to save you from having to explicitly bind functions for use as event listeners.