Playing with the "this" keyword.

Playing with the "this" keyword.

Walkthrough with examples.

The concept that most JavaScript developers struggle with is the this keyword. This comes with a lack of understanding of what this means and how it works.

Determining the this binding for an executing function requires finding the direct call-site(where a function is called from) of that function.

Thumb Rule

The value of this is the object “before dot”, the one used to call the method.

        function foo(){
               console.log(this.a);
         }
         let a = 2;
         foo();    // 2

Here this refers to the global object whether in strict mode or not.

Also, consider the following example,

        function foo(){
               console.log(this.a);
         }
         const obj = {
               a : 4,
         }
         let a = 2;
         obj.foo();    // 4

Using the Thumb Rule this refers to the obj.

Losing this context.

The problem arises when the this keyword loses its context. Consider the following example,

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: foo
};

var bar = obj.foo; // function reference/alias!

var a = "oops, global"; // `a` also property on global object

bar(); // "oops, global"

Here, you would have expected that calling bar() would yield 2 as the output. But it's wrong. The call-site is what matters. The call-site is bar() and thus here this refers to the global object and globalobject.a yields oops, global which is correct output.

Only the top/last level of an object property reference chain matters to the call-site.

Consider,

function foo(){
      console.log(this.a);
const obj1 = {
       a : 2,
      obj2 : obj2,
}
const obj2 = {
      a : 3,
      foo : foo,
}
obj1.obj2.foo(); // 3

Forcing a function call to use a particular object for this binding

function foo() {
    console.log( this.a );
}

var obj = {
    a: 2
};

foo.call( obj ); // 2

foo.call(..) allows us to force its this to be obj.

Arrow functions have no this.

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, lexical this.

Arrow-functions adopt the this binding from the enclosing (function or global) scope.

function greet () {
      return (a)=> {
             console.log(this.a);
     }
}
let obj1 = {
     a : 'Tarun',
};
let obj2 = {
     a : 'Hashnode',
};
let foo = greet.call(obj1);
foo.call(obj2); // 'Tarun' not 'Hashnode' !

Arrow function captures lexical this of greet() at call-time.

References

Wrap Up

This is it for the this keyword. I hope you liked the content, there's more on the way. Stay Tuned! 🔥
If you have any suggestions or questions, please let me know in the comments.