Javascript Tutorial
Javascript Tutorial Introduction to Javascript JavaScript Code Editors & IDE JavaScript Hello World Example Javascript Syntax and Rules syntax_rules javascript_identifiers JavaScript Keywords & Reserved Words javascript_variables JavaScript Const JavaScript let vs var vs const Data Types in JavaScript JavaScript String Template Literals & String interpolation in JavaScript Tagged Templates in JavaScript String to Number in JavaScript Number Data Type in JavaScript NaN in JavaScript JavaScript Number Min & Max & Safe Values JavaScript EPSILON & Floating point precision Infinity in JavaScript JavaScript Bigint BigInt Vs Number in JavaScript Boolean Data Type in JavaScript Undefined in JavaScript Null in JavaScript Null vs Undefined in JavaScript JavaScript Operators Arithmetic Operators in JavaScript Unary plus & minus operators in JavaScript Increment & Decrement Operators in JavaScript Comparison or Relational operators in JavaScript Strict Equality (==) Loose Equality (===) in JavaScript Ternary Conditional Operator in JavaScript Logical Operators in JavaScript Bitwise Operators in JavaScript Assignment Operators in JavaScript Nullish Coalescing Operator in JavaScript Comma Operator in JavaScript Typeof JavaScript Operator Precedence in JavaScript JavaScript if, else & nested if statement Switch Statement in JavaScript While & Do While Loops in JavaScript For Loop in JavaScript Break statement in JavaScript Continue Statement in JavaScript Arrays in JavaScript Array Constructor in Javascript Sparse Array Vs Dense Array in JavaScript How to merge Arrays in JavaScript Array Methods in JavaScript Functions in JavaScript Function Parameters & Arguments in JavaScript JavaScript Default Parameters Pass by Value and Pass by Reference in Javascript Function Expression in Javascript Nested Functions in JavaScript Immediately-invoked Function Expressions (IIFE) JavaScript Callback Functions Arrow Functions in JavaScript Arguments Object In JavaScript Rest Parameters in JavaScript Objects in Javascript Create Objects in JavaScript JavaScript Object Properties Computed Property Names in JavaScript Object Literal in JavaScript Constructor Function & New Operator in JavaScript Delete Operator in JavaScript hasOwnProperty in JavaScript Using Getters and Setters in Javascript DefineProperty in JavaScript JavaScript Property Descriptors Enumerable, Writable & Configurable Object Destructuring in JavaScript Variable Scope in JavaScript Hoisting in JavaScript Lexical Scope & Closures in JavaScript This in JavaScript Global Object, Window & Globalthis in JavaScript Call function in Javascript Prototype In Javascript Prototype Inheritance in JavaScript Instanceof Operator in JavaScript Spread Operator in JavaScript

Arrow Functions in JavaScript

Arrow functions in JavaScript use a concise syntax to create function expressions. JavaScript introduced it as part of ES6 specifications. This article walks you through what Arrow function is, how to create it, and some of its use cases and pitfalls. We also look at how arrow function resolves this and how it is different from a regular JavaScript function.

What is Arrow Function

Arrow functions in JavaScript allow us to use the compact syntax to create the function expression. It uses a “fat arrow” operator, => to separate the function parameters from the function body.

                            
const sayHello = (name) => {
  return "Hello, "+name;
};
 
greet('Paul'); // => 'Hello, Paul
 
 
                            
                        
                            
                        

It is similar to the lambda expressions, which you see in C#, python & Java.

Similar to function expressions., you cannot call an arrow function before declaring it. They are not hoisted like a regular function declaration.

You cannot name an arrow function. They are always anonymous

But the most important distinction between a regular function and an arrow function is how JavaScript resolves this. It resolves it lexically and we will see that using an Example

How to Create a Arrow Function

Take a regular function expression.

                            
sum = function (a,b) {
  return a+b;
}
 
                            
                        
                            
                        

To convert it into an arrow function

  1. Remove the function keyword.
  2. Place a => before curly braces
                            
//Arrow function
 
sum =  (a,b) => {
  return a+b;
}
 
 
sum(10,10) //20
 
                            
                        
                            
                        

The sum is an arrow function. You can invoke it just like a regular function. There’s no difference there.

If the function contains a single return statement then, then you can omit the curly braces & return statement.

                            
sum =  (a,b) => a+b
 
 
                            
                        
                            
                        

But you need to use the curly braces, if it contains more than one statement.

If the arrow function has only one argument, then you can omit the parenthesis

                        
sqr =  a => a*a
 
 
 //or multiline
  
 sum =  a =>  { 
     let c= a+10 ;
     //more statements
     return c;
  }
                                                    
                                                        
                                                    

But if it has no parameter, then a we must add empty parenthesis

                        
sqr =  () => 10*10
                                                    
                                                        
                                                    

In this example, sayHi is our callback function, because it is passed to welcome and invoked by it.

Arrow Function Examples

                        
sayHello = (name) => "Hello " + name;
 
sayHello("Bill")  //Hello Bill
                                                    
                                                        
                                                    
                        
const power = (base, exponent) => {
   let result = 1;
   for (let count = 0; count < exponent; count++) {
      result *= base;
   }
   return result;
};
 

                                                    
                                                        
                                                    
                        
const numbers = [2, 4, 6, 8];
 
const doubled = numbers.map((number) => {
  return number * 2;
});
 
console.log(doubled); // => [4, 8, 12, 16]
 

                                                    
                                                        
                                                    

This and Arrow Function

Arrow functions do not define their own this.

In the scopes in the JavaScript tutorial, we learned that if a function tries to access a variable that is not declared by it, it will look for it in its parent scope. If it does not find it there it will continue to search its parent until it reaches to root scope. This is called Lexical scope.

This is exactly what happens when we try to access this in an arrow function. Since the arrow function does not have a this variable, It will look for it in the enclosing scope. (i.e. outer function if it is inside a function or global if it not inside a function). i.e it resolves this lexically.

Consider the following example.

The obj object has a multiply method. It multiplies each number from the numbers array by a this.factor and returns a new numbers array. obj declares factor as the local variable with a value of 2. We also have a global variable with the same name and with a value of 5.

What is the value of this inside the function ?. Run the code and you will realize that it is a global variable and not from the obj.

                            
Obj = {
    factor: 2,
 
    multiply: function (numbers) {
 
        console.log(this.factor)  //2  
 
        numbers = numbers.map(
 
            //function expression
            function (number) {
                return number * this.factor;
            }
 
        );
 
        return numbers;
 
    }
}
 
var factor = 5
const numbers = [1, 2, 3, 4];
 
console.log(Obj.multiply(numbers))       //5, 10, 15, 20 
 
 
                            
                        
                            
                        

The function expression always declares a this variable. It is given to it by JavaScript when we invoke the function expression (not when we declare it). And its value depends on how we invoke it. Since it is invoked as a standalone function, its this points to the global object. That is why its this.factor value is 5.

Now let us change the example and use the arrow function.

The arrow function does not declare this. If you try to access this it always looks for it in the parent scope. The parent scope comes from the multiply function. We invoke it using method invocation using Obj. ( Obj.multiply(numbers) ). Hence Obj becomes the multiply functions this. So Obj also becomes the this of the arrow function

                            
Obj = {
    factor: 2,
 
    multiply: function (numbers) {
 
        console.log(this.factor)    // 2
        
        numbers = numbers.map(
 
            //arrow function
            (number) =>  {
                return number * this.factor;
            }
 
        );
 
        return numbers;
    }
}
 
var factor = 5
const numbers = [1, 2, 3, 4];
 
console.log(Obj.multiply(numbers))       //2, 4, 6, 8 
 
 
 
                            
                        
                            
                        

Now, let us change the code a little bit. Let us assign the Obj.multiply to another variable ob and invoke it.

Since ob invoked as a standalone function, the global object becomes the this of multiply function. So it also becomes the this of arrow function.

The arrow function does not declare this. If you try to access this it always looks for it in the parent scope. The parent scope comes from the multiply function. We invoke it using method invocation using Obj. ( Obj.multiply(numbers) ). Hence Obj becomes the multiply functions this. So Obj also becomes the this of the arrow function

                            
let ob = Obj.multiply
console.log(ob(numbers));     //5, 10, 15, 20 
 
 
 
                            
                        
                            
                        

We cannot change the this

Arrow functions do not define their own this. Hence you cannot modify something that does not exist. There is no way we can change that.

In the following example, foo returns an arrow function. Hence it is lexically bound to foo. Whatever is the this of foo also becomes this of arrow function

                            
a=1
 
function foo() {
    return () => {
        console.log(this.a);
    };
}
 
//this of foo is global object
b=foo();             
b() 
 
 
                            
                        
                            
                        

Continuing from the above example, we change the this of foo to obj1 using the call method. The arrow function will use the obj1 as it’s this and prints 10

                            
//Here we change the this of foo to obj1 
//using call method
 
obj1 = {  a:10  }
b = foo.call(obj1)
b();                //10
 
                            
                        
                            
                        

Here, we try to change the this of arrow function to obj2 using the call method. But this does not work and the arrow function still uses the this from the foo, which is still obj1

                            
//Changing the this of arrow function to obj2 
//This does not work
 
obj2= {  a:100  }
b.call(obj2);      //10  not 100
 
                            
                        
                            
                        

No constructor or prototype

We cannot use the arrow function as a constructor neither it has a prototype property.

To become a constructor function, the function must declare this. Since there is no this in arrow function, we cannot use it as a constructor function. Since we cannot use them as constructors, there is no need for the prototype property either.

                            
normalAdd=function(a,b) {
    return a+b
}
 
arrowAdd = (a,b) => {
    return a+b
}
 
 
console.log(normalAdd.prototype)    //{constructor: ƒ}
console.log(arrowAdd.prototype)     //undefined
 
 
x=new normalAdd();  //no error
y=new arrowAdd();   //Uncaught TypeError: arrowAdd is not a constructor
  
 
 
                            
                        
                            
                        

No arguments Object

Unlike regular functions, the arrow function also does not have a arguments object.

For Example, you can access the arguments using an Array-like arguments objects. This object is automatically added by JavaScript on function invocation.

                            
function addNumbers(a, b, c) {
 
    console.log(arguments[0]);      //10
    console.log(arguments[1]);      //20
    console.log(arguments[2]);      //30
 
    console.log(arguments[3]);      //undefined
    console.log(arguments[4]);      //undefined
 
    return a+b+c;
 
  }
  
  addNumbers(10, 20, 30);
  
 
 
                            
                        
                            
                        

But arrow functions do not have arguments object.

                            
addNumbers = (a, b, c) => {
 
 console.log(arguments[0]);      //Uncaught ReferenceError: arguments is not defined
 console.log(arguments[1]);      //
 console.log(arguments[2]);      //

 console.log(arguments[3]);      //
 console.log(arguments[4]);      //

 return a+b+c;

}

addNumbers(10, 20, 30);
  
 
 
                            
                        
                            
                        

But that is not a big deal as you can make use of rest parameters (...arguments).

                            
addNumbers = (...arguments) => {
 
 console.log(arguments[0]);      //10
 console.log(arguments[1]);      //20
 console.log(arguments[2]);      //30

 console.log(arguments[3]);      //undefined
 console.log(arguments[4]);      //undefined

}

addNumbers(10, 20, 30);
  
 
 
                            
                        
                            
                        

Arrow functions pitfalls

Because the arrow function resolves this lexically, there are few circumstances where you need to be careful before using them. As a rule of thumb, ensure that you double-check your code, if you are using this in an arrow function.

The following are some of the examples, where you can go wrong.

As Methods of the object

In the following example. sayHello returns undefined for firstName & lastName becuase this here this is a global object and not person object.

While sayHello1 works correctly, because it is a method invocation (person.sayHello1()) Hence the person object is the value of this.

    
// Whatever `this` is here...
var person = {
    firstName: 'Bill',
    lastName:'Jackson',
    sayHello: () => {
        // ...is what `this` is here.
        console.log('Hello '+this.firstName+ ' '+this.lastName);    
    },
 
    sayHello1: function() {
        //we invoked using person.sayHelllo1(). Hence the person is `this` here
        console.log('Hello '+this.firstName+ ' '+this.lastName);    
    }
};
 
 
person.sayHello();     //Hello undefined undefined
person.sayHello1();    //Hello Bill Jackson
 

    

    

As Event Handlers

In EventHandler callback function, every browser sets this to the element which fired the event. Since you cannot change the this of arrow function, you cannot use it here

For Example, the following code does not work, because this inside the arrow function is global object and not username

                            

<head>  

<meta charset="utf-8"> 
</head>
<body>
<h1>Javascript Arrow function Example</h1>
<input type="text" name="username" id="username" placeholder="Enter a username">
<div id="greeting"/div>


<script>
const greeting = document.querySelector('#greeting');
        const username = document.querySelector('#username');
 
        username.addEventListener('keyup', () => {
            //browser cannot inject 'this' becuase arrow function does not allow to change the 'this'
            //'this' comes from the global object
            //Hence 'value' is undefined
            greeting.textContent = 'Hello ' + this.value;
  
        });
</script>
</body>
 
 
                            
                        
                            
                        

But the regular function works, because this here points to username and it is set by the browser.

                            

                            username.addEventListener('keyup', function () {
    //Browser injects 'userName' as 'this' here 
    greeting.textContent = 'Hello ' + this.value;
});