5 Rules to master ‘this’ in Javascript

Few Set of Rules to find out what will 'this' refer to at any point in javascript

5 Rules to master ‘this’ in Javascript

Introduction

Hey readers! This blog is all about 'this' keyword in JavaScript. We'll move from basics and cover all the edge cases where 'this' behaves differently and contains different references.
So from this post, I will try to explain 'this' in JavaScript in the easiest way possible.

The value of this will be determined by the block from where it gets called, but in an order of precedence that we'll discuss here..

  1. Invoking Function with a new keyword -

    When a function gets invoked with a new keyword, the this inside function will refer to a absolutely new empty object.

    function print() {
     console.log(this);
    }
    new print(); 
    // Output: {}
    
  2. Invoking Function with call, apply or bind

    In this scenario, the this will refer to the value that is passed inside the arguments.

    function print() {
    console.log(this);
    }
    const developer= {
    love: "JavaScript"
    };
    const bindedFn = print.bind(developer);
    bindedFn();// { love: "JavaScript" }
    print.call(developer);  // { love: "JavaScript" }
    print.apply(developer);  // { love: "JavaScript" }
    
  3. Invoking Function as a method -

    When a Function is present inside an object with key as some value let's say add and its value as our function then this will be the object that function is a property of.

    const calculate = {
      a: 2,
      b: 3,
      sum: function() {
        console.log(this);
        return this.a + this.b;
      }
    }
    const ans = calculate.sum() // { a: 2, b: 3, sum: ƒ}
    console.log(ans)  // 5
    
  4. Free Function Invocation -

    Free Function Invocation means calling the function without any of the conditions discussed above (without using new operator, or as a method belonging to an object). then this will be the global object.
    In Browsers, global object means the window object but when calling in Strict Mode ('use strict') it will be undefined

    • Free Function Invocation
      function print() {
        console.log(this);
      }
      print() // Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
      
    • Free Function Invocation in Strict Mode
      'use strict'
      function strictFn() {
       console.log(this);
      }
      strictFn(); // undefined
      

    All of the above rules are applied in the precedence from top to bottom. Hence if some rules gets collapsed, the upper one will be applied.

  5. this inside an arrow function -

    Now Things get changed If the function is an ES6 Arrow Function ()=>{}, it doesn't care about any of the rules and receives the this value of its surrounding scope at the time it is created.

    • Regular Function -
      function outer() {
      console.log(this); // { x : 5 }
      const inner = function() {
       console.log(this); // Window {stop: ƒ, open: ƒ, alert: ƒ, ...}
      }
      inner();
      }
      outer.call({x: 5});
      
    • Arrow Function
      function outer() {
      console.log(this); // { x : 5 }
      this.x = 10;
       const inner = () => {
         console.log(this); // { x : 10 }
       }
      inner();
      }
      outer.call({x: 5});
      

      Reasoning -

      As Arrow Functions clearly states that they contain no context to this. In other words, this inside Arrow functions doesn't behave like a context.

      Arrow function will try to resolve this inside it lexically just like any other variable and ask the Outer function - Do you have a this?
      And Outer Function will reply YES and gives inner function its own context to this. That's why this inside an arrow function will always have the context of its surrounding scope.

Test your Knowledge -

Now that you got to know how this works in every scenario, let's see some examples and figure out what will be the value of this.
If are you still not feeling sure or having some doubts, please shoot your queries in the comments I would love to hear them.

  1. const developer = {
     love: 'JavaScript',
     createArrowFn() {
         return () => console.log(this);
     }
    };
    const createArrowFn = developer.createArrowFn();
    createArrowFn(); 
    // Output
    // -> { love: 'JavaScript', createArrowFn: ƒ }
    

    As we learned, when a function is invoked as a property of an object, Its this will refer to the object itself. Thus the this context of createArrowFn will refer to the obj.
    Now we also learned that this inside arrow Fn will refer to this context of its closest surrounding scope so the this inside returned arrowFn will refer to the createArrowFn's this which is the obj itself.

  2. What will be the output ?
    const author = {
     awesome: 'tushar',
     print: function() {
         console.log(this);
     },
    };
    const reader = { awesome: 'me' };
    // DIY - share your solutions with reasoning in comments, I will read them all. ❤
    author.print.call(reader);  // ??
    new author.print() // ??
    

Summary -

  • If the new keyword is used when calling the function, this inside the function is a all new empty object.
  • If apply, call, or bind is used, this inside the function is the object that is passed in as the argument.
  • If a function is called as a method  this is the object that the function is a property of.
  • If a function is invoked as a free function invocation, this is the global object.
  • If it's an arrow function, this value will be the context of its surrounding scope at the time it is created.

If this was helpful and you get some knowledge out of it, please hit the ❤ and share your feedback with me on Twitter .