Understanding this Keyword in JavaScript

this keyword is one of the most confusing in JavaScript. This article will help you understand the value of this keyword contains in different scenarios like in global space, global functions, object literal methods, inner functions, constructor functions, prototype methods, callback functions, controlling the value of this using apply, call, and bind methods. Finally this keyword in event handlers.

this in Global Space

this keyword in global space will always point to window object in browser environment. Try console.log in global space.

//here this will be window
console.log(this);

this in Global Functions

Let’s say you define a function myFunc in global space. Now within any global function, value of this will again be window object.

function myFunc() {
    //this will be window
    console.log(this);
}
 
//call myFunc
myFunc();

Now the question is why it’s point to window object? Remember that any function or data variable defined in global space becomes property of window object. So above function call myFunc() is same as below.

window.myFunc();

Rule 1: this in a function points to its parent/containing object.

myFunc‘s containing object was window so this inside myFunc pointed to window.

this in Object Literal Method

Let me prove again the above rule about function inside an object. Define a method f1 in object literal obj.

var obj = {
    f1: function () {
        console.log(this);
    }
};
 
//this inside f1 will be obj
obj.f1();

As you can see obj is the container for f1 so this in f1 points to obj just like myFunc pointed to window because window was container in that case.

Let’s modify above example to understand another point.

var obj = {
    f1: function () {
        console.log(this);
    }
};
 
//create a reference to f1
var funcAlias = obj.f1;
 
//this inside f1 will be obj
obj.f1();
 
//this inside funcAlias will be window
funcAlias();

As you can see how the function call expression (the way we call a function) changes value of this. If you take a closer look at how funcAlias() works, it still follows Rule 1. As I mentioned before all global variables become part of window object. funcAlias is a global variable so its parent object is window. We can call funcAlias() as window.funcAlias().

Rule 2: You can never judge the value of this by looking at function definition. Always look at function call expression to determine this value.

this in Inner Functions

Let’s say you have an object literal obj and a method outerFunc in it. There’s another function innerFunc in outerFunc as shown below.

var obj = {
    outerFunc: function () {
        //here this will be obj if call expression is: obj.outerFunc()
        console.log(this);
 
        //inner function
        var innerFunc = function () {
            //here this will point to window not matter how outerFunc is called
            console.log(this);
        };
 
        //call inner function
        innerFunc();
    }
};
 
//call outerFunc
obj.outerFunc();

As you can see from the above code, this in innerFunc points to window object no matter how you call outerFunc. So to remain on the safe side, it’s good practice to use that/self pattern.

var obj = {
    outerFunc: function () {
        var self = this;
 
        var innerFunc = function () {
            //use "self" here to access properties of obj
        };
    }
};

Rule 3: this keyword in inner function of object’s method always point to window object no matter how object method is called.

this in Constructor Functions

this in constructor function when called without new operator, points to the containing/parent object just like a method in object literal. You can say constructor function when called without new keyword is exactly the same as other functions so Rule 1 applies to it.

function ConstructFunc() {
   console.log(this);
}
 
//this will be window object
ConstructFunc();

When constructor function is called with new keyword, a new instance is returned and this will point to that newly created instance. Let’s call the above ConstructFunc using new keyword.

//this will point to copy/instance of ConstructFunc
//returned from "new ConstructFunc()"
var instance = new ConstructFunc();

this in Prototype Methods

Let’s define a prototype method for ConstructFunc.

ConstructFunc.prototype.someMethod = function () {
    console.log(this);
};

someMethod is not recognized if ConstructFunc is called without new operator but you can access someMethod from prototype object which is obvious because it’s defined in it.

//TypeError: ConstructFunc.someMethod is not a function
ConstructFunc.someMethod();
 
//this => prototype object
ConstructFunc.prototype.someMethod();

Last statement in above example makes sense and follows Rule 1. this in someMethod points to prototype object because it’s the container object for that method.

Now call the same method using ConstructFunc‘s instance.

var instance = new ConstructFunc();
 
//this => instance
instance.someMethod();

You can see that this in prototype methods point to instance object created using new operator. According to above explanation, Rule 4 can be divided in two parts. First part is when constructor functions are used without creating a new instance using new keyword.

Rule 4.1: this keyword works exactly same as Rule 1 if constructor function is called without new keyword. prototype methods cannot be accessed directly using constructor function like ConstructFunc.someMethod(). But if you access them via prototype object ConstructFunc.prototype.someMethod(), this will point to prototype object itself.

Here’s the second part of Rule 3 when new keyword is used.

Rule 4.2: this points to instance in both constructor function and prototype methods when accessed using instance object.

this in Callback Functions

Callback functions follow Rule 3 i.e. they point to global object (window) because they are called just like inner functions are called. Take a look at following example.

1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {
    ConstructFunc: function (callback) {
       console.log(this);
 
       //always point to window
       callback();
    }
};
 
//callback function is passed to ConstrucFunc
new obj.ConstructFunc(function () {
    console.log(this);
});

A constructor function is defined in object obj which accepts a callback function as parameter. On line 11, a new instance of obj.ConstructFunc is created and callback function is passed which prints the value of this. No matter how you call obj.ConstructFunc, callback will always point to window.

You can control the value of this for callback function using apply, call, or bind functions which are explained in next section.

Controlling the Value of this

apply and call Functions

apply and call are used to call functions but before calling them they bind the value of this to some particular object. So value of this in the called function will point to bounded object. Take a look at following example.

function Person(callback) {
   this.name = 'iFadey';
   callback.call(this);
}
 
new Person(function () {
   console.log(this.name);
});

As you can how this in callback function is bound to Person instance using call function so callback was able to access name property of Person instance. apply function works exactly same as call. The only difference the way how we pass parameters to the called function.

function fullName(fn, ln) {
   console.log(fn + ' ' + ln);
}
 
//call accept each parameter separately
fullName.call(null, 'Fawad', 'Hassan');
 
//apply accept parameters in an array
fullName.apply(null, ['Fawad', 'Hassan']);

Passing null to call or apply function means the value of this in fullName function will be window object.

Lock this Using bind

As you know now how to control value of this using apply or call functions. bind is also used to control this value but it can lock the binding and return a new function. Now value of this will always point to bounded object no matter this function is passed as callback or called directly. Actually bind make use of closure to achieve this kind of locking.

var person = {
   firstName: 'Fawad',
   lastName: 'Hassan'
};
 
function fullName() {
   console.log(this.firstName + ' ' + this.lastName);
}
 
//lock fullName binding with person object
var newFullNameFunc = fullName.bind(person);
 
//prints Fawad Hassan
newFullNameFunc();

As you can see after fullName function is bounded to person and new function is returned in which this is locked to person object. No matter how newFullNameFunc is called, this will always point to person. Here’s the proof.

function otherFunc(callback) {
   callback();
}
 
//still prints Fawad Hassan
otherFunc(newFullNameFunc);

bind function can also be used to achieve Partial Function Application. Here’s a simple example.

function sum(a, b) {
   console.log(a + b);
}
 
//sum5 is locked to window object and
//its first parameter is also locked to 5
var sum5 = sum.bind(null, 5);
 
//now we can call sum5 by passing only the second parameter
//in this case it prints 8
sum5(3);

this Keyword in Event Handlers

this in event handler points to the HTML element for which it’s fired.

document.querySelector('#someDiv').addEventListener('click', function () {
   //this => #someDiv element
   console.log(this);
}, false);

Event handlers also follow Rule 1 because every element contain the events as properties like click, blur, etc. Another interesting point is the case of single function acting as event handler for different elements. this keyword in such case will always point to the element for which it’s fired. Take a look at this example.

function handler() {
   console.log(this);
}
 
//this => #someDiv
document.querySelector('#someDiv').addEventListener('click', handler, false);
 
//this => #btn
document.querySelector('#btn').addEventListener('click', handler, false);

handler function acts as click event handler for both someDiv and btn but you can see that this points to the element for which it’s acting as event handler.

Rule 5: this keyword in event handler points to the HTML element for which it’s fired.

Summary

Rule 1: this in a function points to its parent/containing object.

Rule 2: You can never judge the value of this by looking at function definition. Always look at function call expression to determine this value.

Rule 3: this keyword in inner function of object’s method always point to window object no matter how object method is called.

Rule 4.1: this keyword works exactly same as Rule 1 if constructor function is called without new keyword. prototype methods cannot be accessed directly using constructor function like ConstructFunc.someMethod(). But if you access them via prototype object ConstructFunc.prototype.someMethod(), this will point to prototype object itself.

Rule 4.2: this points to instance in both constructor function and prototype methods when accessed using instance object.

Rule 5: this keyword in event handler points to the HTML element for which it’s fired.


comments powered by Disqus