Understanding THIS in Javascript

Introduction

One of the most confusing and misused keyword in javascript is this keyword.For a javascript beginner, this feels like shrouded in mystery.But if properly used, this can be proved as a valuable asset in the toolbox of a javascript developer.Here I would like to shed some light on what this actually is and techniques to manipulate this in a javascript application.The concept might appear too difficult to wrap you head around,but if you give effort and practice the concept by writing small code you will get the hang of it eventually.You could just follow along and try out the code provided in the discussion in your browser.

Let's Talk About Scope

Any javascript programmer using this without any prior knowledge of the outcome of the code may caught up in a situation which is hard to debug, confusing and very difficult to fix. To understand this one must have clear understanding of another beautiful concept of javascript which is called scope. Before getting into how this works and how we can manipulate it, I would like to discuss a bit about the concept of scope.

We all know global variables, right? These are the variables which can be accessed from anywhere in your javascript code.A variable's visibility depends on its scope. Global variables can be accessed from global scope and function scope (Local Scope) equally. Chances are that you might not be familier with the concept of scope. So,I would like to discuss here about the concept of scope in a nutshell.

Scope determines the visibility level...........

Simply put, Scope controls the visibility of a variable. Variables declared in global scope , has global visibility.They are accessible from anywhere in the script.On the other hand local variable resides in local scope (alos known as function scope). Visibility of local variable is limited to local scope. Generally Outside environment can not access a local variable. Of course there are some ways to interact with local variables from outside environment, But that discussion is for later.For now let's just stick to the fact that local variables are confined to local scope. They are only available in local scope. So we can say, javascript deals with two different kinds of scopes,They are :

  • Global Scope
  • Function Scope (Local Scope)

Here is a visual illustration for the secret world of javascript. Following illustration will provide a better understanding on relationship between variables and scope in javascript.

//javascript world
--------------------------------------------------------------------------------
-                                                                              -
-   //Global Scope                                                             -
-   //Declare Global Variable Here in Global Scope                             - 
-   var global_var = "global variable" //here global_var is a global variable  -
-                                                                              -
-   function sample_js_function(){                                             -
-                                                                              -
-      var local_var = "local variable" // it's a local variable               -
-                                                                              -
-         /*                                                                   -
-          function scope resides inside a function                            -
-          inside a function we can declare local variable                     - 
-          Local variables can't be accessed from outside of the function      -
-          scope but we can access any global variable from here               -
-          global_var  can be accessed within `this` function                    -
-         */                                                                   -
-                                                                              -
-     }                                                                        -
-                                                                              -
--------------------------------------------------------------------------------

Above illustration explains that global variable can be accessed from both in global scope (obviously, as they are created in global scope) and Local scope(Within any function).

keep in mind that this refers to global object (window object) by default.Any global variable becomes a property of global object.We can access any global variable through this keyword.this is analogas to window object. If we check strict equality between this and window , it will return true

 this === window // true

Let's justify what i've just said with an example.For this, we need to create a global variable first. Let's create one

var global_var  = "a global variable" 

If we want to see what value our global_var variable holds, we can access it directly by the variable name

console.log(global_var) // prints "a global variable"

On the other hand, as we already know global variables are added to global/window object as property,we can also access the global_var variable through global object or window object

console.log(window.global_var) // access global_var through window object, prints "a global variable"
& 
console.log(`this`.global_var) // access global_var thorugh `this`. So, `this` === window

both works equally.

What this is all about ?

What you have just learned about scope will help you to understand this with more clarity. As I've already mentioned,this refers to the EXECUTION CONTEXT. Execution context is a topic for another discussion. What you need to know is,execution context indicates which object is bound to the current scope.

Execution context refers to the object which is bound to the current scope

If it feels confusing, don't worry. Following example will clarify your confusion. If you pay close attention, you will apprehend the general idea about execution context and why it is responsible for determining what this will be pointing to during javascript execution.

this refers to execution context

If you go through the illustration I've given while discussing scope, you will see that inside javascript world there are two different kinds of scope ,one is global and another is local. When javascript begin executing the code, it first enters into the global context. Global context is window. So in global context(or I can say global scope), this refers to window. Concept of scope and context are related to each other.Let's explain the relation between scope and context First :

- At the beginning of execution,javascript engine enters into global scope.So,execution context is global.So this will point to global object.

- When we invoke any function ,javascript engine enters into that function's local scope.But Execution context will still be global, so this will still point to global object inside that function's local scope.

- If we bind the function with an object other than global object, context will refer to that bound object inside the function's private scope instead of global object.So this will now become that particular object.

- After function execution is over,javascript engine jumps out of the function and land into global scope again.So this will refer to global/window object again.

Let's explain the five points stated above with an example.


console.log(`this`) // here `this` refers to global/window

var person = {

     username : "zami",

     sayName  : function(){

            console.log(`this`) // here `this` will be person

            console.log(`this`.username) //prints the value of username property

            function inner(){

                console.log(`this`) // here `this` will be window or global/window object

            }

            inner() // invoke inner function

        }

}

person.sayName() //  invoke sayName 

/*
 Now execution context will jumps back into global context right after 
 finishing function execution.
 As execution is out of a function's private scope, it will again 
 point to global object

*/
console.log(`this`) 


What's going on here? Let's explain step by step.Here I have a person object.It has a property called username and a method called sayName. Inside sayName there is another function called inner.

At the beginning of execution, javascript engine enters into the global context. That's why this refers to global object inside global scope.

console.log(`this`) // so, it will pint window object in the console

Then, it found an object called person and maps it into memory.Then it finds an invocation of sayName method of the person object.

person.sayName() // it invokes sayName method and set `this` inside the function to person object

That implies why the first console.log(this) inside sayName method prints person object in the console.Because as we invoked the sayName method under the context of person object, this will not set to person object. That makes sense why putting a console.log(this.username) inside sayName method will print the value of username property of person object.

Now execution comes to the invocation of inner function. The point is, when javascript engine maps internal variables and function of an object to memeory, it doesn't bind the context object to the functions that are declared inside a particular object method. That means person object is not boudn with the inner function. As a result inner function fall subject to default binding which is global object.Thats why console.log(this) inside inner function prints window in the console. So, this refers to the global/window object inside inner function.