Javascript - this in Arrow Functions

Introduction

this refers to the enclosing context where the arrow function is defined.

Unlike a normal function, an arrow function does not create its own execution context.

It takes this from the outer function where it is defined.

function Employee(firstName, department, salary) { 
    this.firstName = firstName; 
    this.department = department; 
    this.salary = salary; 

    this.getInfo = function() { 
        // outer function context = Employee object 
        return function () { 
            // inner function context = Global object 
            console.log(this.firstName + " from " + this.department + " earns " + this.salary); 
        }; 
    } 
} 

let anEmp = new Employee('Jim', 'Finance', 5200); 
anEmp.getInfo(); 

Here, we created a constructor function called Employee.

The code created a new employee object called anEmp using the constructor function with the new keyword.

In order to print the employee information, we need to use the function returned by anEmp.getInfo().

let printInfo = anEmp.getInfo(); 
printInfo();  // undefined from undefined earns undefined 

Here, printInfo refers to the inner function.

Since we are making a function invocation, this refers to the Global object that does not have any Employee properties and hence produces undefined whenever a property on this is used.

The following code shows how this behaves differently if we replace the inner function with an arrow function:

function Employee(firstName, department, salary) { 
    this.firstName = firstName; 
    this.department = department; 
    this.salary = salary; 

    this.getInfo = function() { 
        // outer function context = Employee object 
        return () => { 
            // inner function context = surrounding context = Employee object 
            console.log(this.firstName + " from " + this.department + " earns " + this.salary); 
        }; 
    } 
} 

let anEmp = new Employee('Jim', 'Finance', 5200); 

let printInfo = anEmp.getInfo(); 
printInfo();  // Jim from Finance earns 5200 

Here, the this keyword refers to the context of the function enclosing the arrow function.

Arrow functions do not change their context on invocation.

function Employee() { 
    this.firstName = 'Mike', 
    this.department = 'HR', 
    this.salary = 4500, 

    this.getContext = () => { 
        console.log(this); 
    } 
} 

let mark = new Employee(); 
mark.getContext(); // [Employee object] 

let context = mark.getContext; 
context(); // [Employee object] (regardless of a function invocation) 

Here, the context of the arrow function was set on declaration and it cannot be changed.

You cannot "rebind" an arrow function. The context is fixed.

var details = { 
    number: 42, 
    operation: function () { 
       return () => console.log(this.number); 
    } 
}; 

var details2 = { 
        number: 84 
}; 

details.operation().bind(details2)(); // 42 

Inside an array function the value of the this keyword cannot be changed.

The value of this inside an array function will remain constant, but you can use bind, call, and apply on arrow functions.

var product = (x, y) => x * y; 

console.log(product.call(null, 2, 3));           // 6 
console.log(product.apply(null, [2, 3]));        // 6 

var multiply = product.bind(null, 2, 3); 
console.log(multiply ());                        // 6 

arrow functions have lexical arguments inherited from their parent.

There are no this, super, arguments, and new.target bindings for arrow functions.

Arrow functions cannot be called with new since they do not have the construct method and cannot be used as constructors.

They will produce an error when used with new.

var newFn = () => {}, 
object = new newFn();  // error - you can't use arrow functions with 'new' 

Functions declared using arrow function, do not have access to a prototype field.

var details = () => 42; 

console.log(details.hasOwnProperty("prototype")); // false 

Arrow functions cannot have duplicate named parameters in either strict or non-strict mode.

Related Topic