What the fuck "this" is ?

Trying to understand "this"

Regular Function

In regular function "this" would reference to on which that function is called, otherwise "this" will be global ( in browser "window").

In case, of call/apply/bind, this will refer to object on which that function/method is called

Arrow Function

Arrow functions are special: they don’t have their “own” this. If we reference this from such a function, it’s taken from the outer “normal” function (aka outer lexical environment).

Consider the following example, and see how "this" behave differently for regular and arrow function

const collegeGroup = {
    title:  "King's Sqad",
    students: ["Azeem", "Pal", "PK"],

    displayList() {
      this.students.forEach((student) => {
       // Takes 'this' from displayList() function (outer lexical scope)
       console.log(`${this.title} - ${student}`);
      });
    },
    displayListV2() {
      this.students.forEach(function (student){
       //forEach runs functions with this=undefined by default,  so 'this' it will be undefined
       console.log(`${this.title} - ${student}`);
      })  
    }
}

collegeGroup.displayList() //  ??
collegeGroup.displayListV2() // ??

So arrow function does't have "this", means they can't be used as constructor and can't be called as "new" â˜ș

Again, arrow ⇒ does't have "this", so .bind(this) does't create any binding for arrow function and lookup of "this" will look into outer lexical environment.

Arrow function does't have "arguments" like normal function

What is special object "arguments" in Javascript ?

In JavaScript, regular functions have a special object called arguments. This object is like an array that holds all the values passed into the function when it's called, even if those values weren't defined as parameters in the function's declaration.

See below example:

function AplusB() {
   const [a, b] = arguments;
    return a + b;
}

console.log(AplusB(1, 2)); 

Arrow functions have no super

Example of "super"

So arrow functions do not have super. If accessed, it’s taken from the outer function. For instance:

class Animal {
  constructor(name) {
   this.name = name;
  }
  stop() {
   console.log("Animal's stop() is exectuted")
  }
}

class Rabbit extends Animal {
 stop() {
    setTimeout(() => super.stop(), 1000); // call parent stop after 1sec
    // setTimeout(function() { super.stop() }, 1000) 
    console.log("Rabbit's stop() is exectuted")
 }
}

// Run
const myAnimal = new Rabbit("Roocca");
myAnimal.stop() // 

Now, use following in-place of arrow function:

setTimeout(function() { super.stop() }, 1000);

And this would give error SyntaxError: 'super' keyword unexpected here

Related to Inheritance, but worth to share here, and you can think why both print the same ?

class Animal {
  name = 'animal';
  
  constructor() {
   console.log(this.name); 
  }
}

class Rabbit extends Animal {
  name = 'rabbit';
}

new Animal(); // animal
new Rabbit(); // animal

Answer: The parent `constructor` always uses its own field value for "this", not the overridden one.


Example:

const bankAccount1 = {
  name: "ABC 1",
  display: function() {
    console.log(this.name);  

    // Inner function as normal function
    const innerDisplay = function()  {
        console.log(this.name);
        // callback function as normal function (*)
        setTimeout(function() { console.log(this.name); }, 0)
     };
      
    innerDisplay();
  }
};

const bankAccount2 = { name: "ABC 2" };
bankAccount2.newDisplay = bankAccount1.display;

Question: 1 can we tell the output of bankAccount1.display();?

Question: 2 can we tell the output of bankAccount2.newDisplay();?

Question: 3 Change line (*) to use arrow function as setTimeout(function() { console.log(this.name); }, 0) and then tell the output of above two questions ?

Answers

Answer 1: bankAccount1.display();

ABC 1
undefined
undefined

Answer 2: bankAccount2.newDisplay();

ABC 2
undefined
undefined

Answer 3 After changing it to arrow function

bankAccount1.display()
ABC 1
undefined
undefined


bankAccount2.newDisplay();

ABC 2
undefined
undefined

Last updated