Javascript Tutorial
Javascript Tutorial Introduction to Javascript JavaScript Code Editors & IDE JavaScript Hello World Example Javascript Syntax and Rules syntax_rules javascript_identifiers JavaScript Keywords & Reserved Words javascript_variables JavaScript Const JavaScript let vs var vs const Data Types in JavaScript JavaScript String Template Literals & String interpolation in JavaScript Tagged Templates in JavaScript String to Number in JavaScript Number Data Type in JavaScript NaN in JavaScript JavaScript Number Min & Max & Safe Values JavaScript EPSILON & Floating point precision Infinity in JavaScript JavaScript Bigint BigInt Vs Number in JavaScript Boolean Data Type in JavaScript Undefined in JavaScript Null in JavaScript Null vs Undefined in JavaScript JavaScript Operators Arithmetic Operators in JavaScript Unary plus & minus operators in JavaScript Increment & Decrement Operators in JavaScript Comparison or Relational operators in JavaScript Strict Equality (==) Loose Equality (===) in JavaScript Ternary Conditional Operator in JavaScript Logical Operators in JavaScript Bitwise Operators in JavaScript Assignment Operators in JavaScript Nullish Coalescing Operator in JavaScript Comma Operator in JavaScript Typeof JavaScript Operator Precedence in JavaScript JavaScript if, else & nested if statement Switch Statement in JavaScript While & Do While Loops in JavaScript For Loop in JavaScript Break statement in JavaScript Continue Statement in JavaScript Arrays in JavaScript Array Constructor in Javascript Sparse Array Vs Dense Array in JavaScript How to merge Arrays in JavaScript Array Methods in JavaScript Functions in JavaScript Function Parameters & Arguments in JavaScript JavaScript Default Parameters Pass by Value and Pass by Reference in Javascript Function Expression in Javascript Nested Functions in JavaScript Immediately-invoked Function Expressions (IIFE) JavaScript Callback Functions Arrow Functions in JavaScript Arguments Object In JavaScript Rest Parameters in JavaScript Objects in Javascript Create Objects in JavaScript JavaScript Object Properties Computed Property Names in JavaScript Object Literal in JavaScript Constructor Function & New Operator in JavaScript Delete Operator in JavaScript hasOwnProperty in JavaScript Using Getters and Setters in Javascript DefineProperty in JavaScript JavaScript Property Descriptors Enumerable, Writable & Configurable Object Destructuring in JavaScript Variable Scope in JavaScript Hoisting in JavaScript Lexical Scope & Closures in JavaScript This in JavaScript Global Object, Window & Globalthis in JavaScript Call function in Javascript Prototype In Javascript Prototype Inheritance in JavaScript Instanceof Operator in JavaScript Spread Operator in JavaScript

This in JavaScript

“this” in JavaScript is an object. Every JavaScript function gets a copy of this (except arrow functions). Its value does not depend on where we declare it but on how we invoke it. There are four ways in which we can invoke a function. They are Function invocation, method invocation, Constructor invocation & Explicit invocation. Each of these invocations sets the value of this differently. This tutorial will dive deep into this in JavaScript and learn more about it.

What is “this” in Javascript

Take a look at the following person object. It contains the method sayHello. How do we get to the person’s name from within sayHello?

We use “this” keyword to access the person object.

Inside the sayHello function, the this keyword refers to the person object. Using this keyword, we can refer to all properties and methods of the person object inside the sayHello function.

Example

            
person= {
    name:"Gregory Peck",
    sayHello:function () {
        console.log("Hello "+ this.name)   //using this here
    }
}
person.sayHello()   // Hello Gregory Peck
                
        
    

We say this is bound to the person object inside the sayHello function.

this is an object to which function is bound to in the run time. The run-time binding of a function can change depending on how we invoke it. If there is no binding is found, then it defaults to the global object in nonstrict mode and undefined in strict mode.

Why “this” in JavaScript is so Confusing

In languages like c#, java, etc., this always points to the current class instance to which the method belongs. This is very intuitive and easy to grasp. The methods are bound to the class. You cannot change those bindings.

But there is one critical difference between functions in JavaScript and those in c# or Java. In JavaScript, functions are objects. They are not bound to anything. So, you can assign them to another variable, pass them around, etc.

But there is one critical difference between functions in JavaScript and those in c# or Java. In JavaScript, functions are objects. They are not bound to anything. So, you can assign them to another variable, pass them around, etc.

The obj object declares the foo function and becomes the obj‘s method. When we invoke the foo function using obj.foo(), it prints the value of a (i.e., 10) from the obj and not from the global value of a. Here this inside the foo points to the obj itself. This is precisely how this works in C# & Java.

Example

            
a=1;
 
obj = {
    a:10,
   
    foo:function () {
        console.log(this.a)
    }
}
 
obj.foo()   // 10

                
        
    

In the following example, we copy foo to another variable, boo. Now boo also points to the foo function, but it is not associated with the obj.

When we invoke boo, this points to the global object rather than foo. That is why it prints 1 instead of 10.

Example

            
a=1;
 
 obj = {
     a:10,
    
     foo:function () {
         console.log(this.a)
     }
 }
  
 boo=obj.foo
  
 //Both of these call the foo function. But get different value for 'this' 
 obj.foo()   // 10   'this' is obj
 boo()       // 1    'this' is global object
  

                
        
    

We can also assign the function as the property of another object. The following example attaches foo to another object, obj2. When we invoke obj2.foo(), this of the foo points to obj2.

Example

            
obj2= {
    a:100,
    foo:obj.foo
}
 
obj2.foo(); // 100
 
  

                
        
    

So when you declare a function, you will never be sure what would be its “this". Because it never depends on where you declare it. But it depends on how you use it. The same function invoked differently gets different values for this.

Example

            
obj2= {
    a:100,
    foo:obj.foo
}
 
obj2.foo(); // 100
 
  

                
        
    

This outside a function

The value of this outside of a function is always the global object.

The global object always exists in JavaScript applications. But what value it takes depends on where we run our app.

Inside the browser, the global object is window, while in NodeJS it is an object named global. The value does not depend on strict mode.

Example

        
 console.log(this)  //Always window inside a browser, global inside a NodeJs
  
    
        
    

How to identify this in Javascript

Value of “this” inside a function depends on how & where we invoke the function and whether the strict mode is enabled or not.

There are four ways in which you can invoke a function. They are

  1. Function Invocation
  2. Method Invocation
  3. Constructor invocation
  4. Explicit invocation

Each of the above Invocations sets the value of this differently. In the case of function invocations, the Strict Mode also affects the value of this.

Function Invocation or Default Binding

When we invoke a function as a standalone function (not as a property of an object), then we call that function Invocation.

In a function invocation this is bound to the global object in “not strict” mode. But if we use “strict” mode this is always null.

The window object is the global object in the web browser, while in NodeJs an object called globalThis is the global object

Example

        
function hello() {
    console.log(this==window)  //Window
}
 
hello()    //'this' here is window
  
    
        
    

Invoking a Function expression.

Example


hello = function() {
console.log(this==window)  //Window
}

hello()    //'this' here is window


But in a strict mode, this is undefined

Example


"use strict"

function hello() {
console.log(this==window)  //false
console.log(this)          //undefined 
}

hello()    //'this' here is undefined


You can also use use strict inside the function, but it must be at the beginning of a function.

Example


function hello() {
"use strict"
console.log(this == window)  //false
console.log(this)          //undefined 
}


hello()    //'this' here is undefined becuase hello uses  "use strict"


Method Invocation (Implicit Binding)

The method is the function that we declare as the property of an object. When we invoke the method using the property accessor ( using dot or [] ), we call it method invocation.

In a method invocation, the object that invokes the method becomes the this of the method.

The following codes are examples of method invocation.

Example

        
foo.getName();       //this == foo 
foo["getName"]()     //this == foo 
 
 
boo.getName();      //this == boo
    
        
    

The last level of the object becomes this. In the following chained call foo comes last. Hence it becomes this.

Example

        
boo.foo.getName()   //this == foo
 
    
        
    

The getName method inside foo, boo & bar refers to the global getName function.

Example

        
getName = function () {
    console.log(this.name)  
}
 
 
foo = {
    name:"foo",
    getName:getName
}
 
 
foo.getName();      //foo
 
 
boo = {
    name:"boo",
    getName:getName
}
 
 
boo.getName();      //boo
 
 
bar = {
    name:"bar",
    foo:foo,
    boo:boo,
    getName:getName
}
 
bar.foo.getName()    //foo
bar.boo.getName()    //boo
bar.getName()        //bar
    
        
    

Remember dot is not the only way to invoke a method. You can also make use of a bracket.

Example

        
var counter = {
    value: 0,
    increment: function () {
       console.log(++this.value);
        
    }
};
 
counter.increment();     //'this' = counter
counter["increment"]();  //Another way to invoke a method
    
        
    

Inner function looses this binding

In the following example, we attach the outer function as method to obj object. Inside the outer function, we have inner function.

We invoke the outer function as method invocation (obj.outer()). Hence obj becomes the this of the outer function.

But inside the outer function, we invoke the inner function using the function invocation. Hence it gets the window object as its this

Example

        
var val=10          
 
let obj = {
 
    val:100,            //property of the obj
 
    outer:function() {
 
        //'this' here is obj. 
        // Hence we can access its property
 
        console.log(this==obj)  //true
        console.log(this.val)   //100
 
        let inner = function() {
 
            //'this' here is window not obj
            console.log(this==window)  //true 
 
            //val comes from the golbal variable            
            console.log(this.val)      //10
        }
    
        inner();   //function invocation.'this' is window
    
    }
};
 
obj.outer();  //method invocation 'this' of outer function is obj
    
        
    

Workaround for the inner function

There is a simple way by which we can make the Inner function to access this from the outer function.

To do that create a local variable in the outer function. Name it as that. Assign this to that. Now you can access the that variable in the inner function

Example


var val=10          
 
let obj = {
 
    val:100,            //property of the obj
 
    outer:function() {
 
        //'this' here is obj. Hence we can access its property
        console.log(this==obj)  //true
    
        //define a local variable `that` and store `this` in it. 
        let that=this;          
 
        let inner = function() {
 
            //'this' here is window not obj
            console.log(this==window)  //true 
 
            //`that` comes from the parent scope
            console.log(that==obj)     //true 
 
            //use that
            console.log(that.val)      //100
        }
    
        inner();   //function invocation
    
    }
};
 
obj.outer();  //method invocation


Separate method from the object

In the following example, we assign obj.testFunction() to a variable fn. The fn variable contains the reference to the testFunction

When we invoke the testFunction using the method invocation (i.e., obj.testFunction()), the obj becomes the this of the testFunction.

But when we invoke it using the function invocation (i.e., fn()), then the window becomes the this of testFunction.

To do that create a local variable in the outer function. Name it as that. Assign this to that. Now you can access the that variable in the inner function

Example


var val=10          
 
let obj = {
 
    val:100,        
 
    testFunction:function() {
        console.log(this==window)    //Check for globalThis if you using nodeJs
        console.log(this==obj) 
        console.log(this.val)     
    }
};
 
fn= obj.testFunction;  //assigning to a varible
 
obj.testFunction() //method invocation. 'this' of testFunction function is obj
 
//false
//true
//100
 
fn()  //function invocation. 'this' of the testFunction function is window
 
//true
//false
//10
 


But we can force the outer function to use the obj as this by using the method bind. This is called explicit binding. We will talk about it later

Example


fn= obj.testFunction.bind(obj);  
fn()
 
//true
//false
//100
 
 


Constructor Invocation or New Binding

We can also invoke a function using a new Operator. We usually use the new operator on a Constructor function to create a new object. But we can use the new operator on any function.

If the function is invoked with new keyword, then the this is a new object

Example

        
function hello() {
 
 //It is not window
 console.log(this==window)  //false

 //it is not even hello
 console.log(this==hello)  //false

 //'this' is an empty object
 console.log(this)
}


new hello();   //constructor invocation. 'this' is a new empty object

    
        
    

If you invoke a function without new keyword it will be a function invocation. In that case the this will be global object

Example

        
//this is a function invocation. 
//'this` is global object
hello();
 
    
        
    

You can read more about constructor function and new operator

Explicit Binding

We can also set the value of this explicitly. i.e. we pass the value of this, when we invoke the function overriding the JavaScript generated this. This is useful when we make use of the callback functions

There are three methods that allow us the set the this of an object. All of them are available in the function.prototype object.

  1. Call
  2. Apply
  3. Bind

Call

The call() method invokes a function. It sets the first parameter as the this of the function

For Example, the foo.call method invokes the foo method. The first argument bar becomes the this of the foo function

Example

        
var a =1
 
function foo() {
  console.log( this.a );
}
 
var boo = {
  a:10,
  foo:foo
}
 
 
var bar = {
  a: 100
};
 
foo();     //5  Function invovation, 'this' here is global object
boo.foo() //10  Method invocation.  'this' is boo
 
//Explicit binding
 
foo.call(bar);        //100  Sets 'this' of foo to bar and invokes it
boo.foo.call(bar)  //100  Sets 'this' of foo to bar and invokes it
 
    
        
    

Call

The apply() method invokes a function. It sets the first parameter as the this of the function

The apply method is very similar to the call method. They only differ in how they define the second parameter. The apply method excepts an array as the second parameter.

The call() method invokes a function. It sets the first parameter as the this of the function

You can easily replace call in the previous example to apply.

Example

                            
var a =1
 
function foo() {
  console.log( this.a );
}
 
var boo = {
  a:10,
  foo:foo
}
 
 
var bar = {
  a: 100
};
 
foo();     //5  Function invovation, 'this' here is global object
boo.foo() //10  Method invocation.  'this' is boo
 
//Explicit binding 
 
foo.apply(bar);     //100  Sets 'this' of foo to bar and invokes it
boo.foo.apply(bar)  //100  Sets 'this' of foo to bar and invokes it



Bind

The bind method allows us to change the this of a function and invoke it any time later. bind method does not invoke the function, but it returns a new function

For Example, the code s2=obj.show.bind(obj) sets the this of method show to obj and stores it in variable s2. Now we can invoke s2 anytime, it is always hardbound to obj.

Example

                            
var value=10
 
 obj = {
   value:100,
   show:function() {
     console.log(this.value)
   }
 }
  
  
 obj.show()      //100   method invocation 'this' is obj 
  
 s1=obj.show     //function separated from the obj
 s1()            //10    Function invocation 'this` is global object. 
  
 //Using bind
  
 s2=obj.show.bind(obj)   //s2 is a function now hard bound to obj
 s2()            //100  Function invocation. but function is hard bound. hence 'this' is global object
 s2()            //100  



Internally bind returns a wrapper function, which uses the apply method to bind the object to this.

Example

                            
function bind(fn, obj) {
   return function() {
     return fn.apply( obj, arguments );
   };
}  



Primitive Values & Explicit binding

If we pass a primitive value to call, apply or bind, they will convert it into its object representation. For Example, the string is converted to an object into using new String()

Passing null or undefined to bind, call & apply

The bind, call & apply functions ignores the null or undefined. instead, they will use the default binding.

Exceptions

There are Exceptions to the above rules of determining this.

Arrow functions

The arrow functions do not declare any this. Hence if we try to access this it will look for it in its parent scope.

You cannot even change the this of arrow function using apply, call or bind methods. i.e. because the arrow function does not have this

For Example, we use the arrow function for the getName method. It will return undefined because “this” for arrow function comes from its parent scope, which is the global scope.

Example

                            
var person = {
    firsName:'Alex',
    lastName:'Ferguson',
    getName: () => console.log(this.firsName+' '+this.lastName)
 
}
 
person.getName();   //undefined Method Invocation. But Since it is an arrow function 'this' is global object


Hence it is usually not recommended to use the arrow function as the method of an object.

Example

                            
var person = {
    firsName:'Alex',
    lastName:'Ferguson',
    getName()  {
        console.log(this.firsName+' '+this.lastName)
    } 
 
}
 
person.getName();   //Alex Ferguson Method Invocation.'this' is person


For Example, you can refer to the This and arrow function

This in an ES6 Module

Inside an ES6 Module but outside the function this is always undefined. Also, ES6 Modules always runs on strict mode.

Hence the value of this inside a function invoked using function invocation is always undefined in an ES6 Module. However, the other types of function invocation like method, constructor invocation & explicit bindings work as mentioned above.

Precedence

It also important to know the Precedence of this binding. It is actually possible two bindings in a function call

  1. New binding or constructor calls
  2. Explicit Binding
  3. Method invocation or implicit binding
  4. Default binding

Default binding

Example

        
obj1= {
    name:"Bill",
    hello: function() {
        console.log(this) 
    }
}
 
 
obj2= {
    name:"Alex",
    hello: obj1.hello
}
 
hello=obj1.hello;
 
 
hello()           //'this' = window   
obj1.hello()       //'this' = obj
 
//New
new obj1.hello()   //'this' = new object.  new takes precedence
new obj2.hello()   //'this' = new object.  new takes precedence
 
obj1.hello.call(obj2)  //this = obj2.  binding has higher precedence
    
    
        
    

Summary

Finally the summary of determining the this

  1. If we invoke the function with a new operator, this is always a new object.
  2. The function invoked with the call, apply & bind methods uses the first argument as their this. But if you pass null or undefined as the first argument, they use the default binding.
  3. The method invocations use the context object (i.e., object left of the dot notation)
  4. If all of the above fails, then use the default binding. It is null in the case of strict mode. Else global object (window in browser, global in NodeJs).