Understanding ‘ this ’ in JavaScript

Keeping track of what this refers to in a JavaScript function can be tough and at times confusing. This article aims to make this keyword easier to comprehend once and of all, so let’s begin.

‘this’ outside a function.

In the global execution context, this assumes the value of global object ( global in Node JS and window in browser).

var globalObject = this;
/*      Node js     */
globalObject === global; //true
/*      Browser     */
globalObject === window; //true

‘this’ inside a function.

The value of this inside a function is set at time of function invocation using either of Property accessors (‘ . ’ or ‘ [ ] ’ operators).

  • When a function is invoked using ‘ . ’ operator, this is set to the corresponding context object.
  • When a function is invoked without the use of ‘ . ’ operator , this will default to the global object (this type of function invocation is commonly termed as a “simple call”).

Now let us try some examples to make my point clear.

  • Example 1:
function f1() {
return this;
}
var myObj = {
method: f1
}
f1() === global; //true
myObj.method() === myObj; //true
  • Example 2:
var myObj = {
method: function() {
return this;
}
}
myObj.method() === myObj; //true
var f = myObj.method;
f() === global; //true

Here note that even though the function resides inside myObj, it’s this value is set to global when using a reference.

  • Example 3:
function add(a, b, callback) {
callback(a + b);
}
var myObj = {
p: 1,
q: 2,
findSum: function() {
add(this.p, this.q, function(sum) {
console.log(sum);
console.log(this === global);
});
}
};
myObj.findSum(); 
*/ prints the following output.
3
true

*/

Here callback is invoked with a simple call, so it’s this will default to global. Since this is the case for every callback in JS we can conclude ..

Every callback function has a this binding of global, unless otherwise this is explicitly set .

That’s enough examples, we shall now see how to change this default behavior…

call( ) and apply( ) :

When ever a function is invoked, it can bind to a context of our choice using either call( ) or apply( ).

function greetPerson (firstName, secondName) {
var greetings = this.greet + ' ' + firstName + ' ' + secondName;
console.log(greetings);
}
var obj1 = { greet: 'Hello' };
var obj2 = { greet: 'Ola' };
/* call({context}, param1, param2...) */
greetPerson.call(obj1, 'Pavan', 'Varma') // Hello Pavan Varma
greetPerson.call(obj2, 'Pavan', 'Varma') // Ola Pavan Varma
/* apply({context},[param1, param2...]) */
greetPerson.apply(obj1, ['Pavan', 'Varma']) // Hello Pavan Varma
greetPerson.apply(obj2, ['Pavan', 'Varma']) // Ola Pavan Varma

bind( ):

Every function has a prototype method bind, which when invoked with some object creates a new copy of that function bound to that object.

function greetPerson (firstName, secondName) {
var greetings = this.greet + ' ' + firstName + ' ' + secondName;
console.log(greetings);
}
var obj1 = { greet: 'Hello' };
var obj2 = { greet: 'Ola' };
/*       A new function bound to obj1     */
var greetPersonHello = greetPerson.bind(obj1);
greetPersonHello('Pavan', 'Varma');       // Hello Pavan Varma
greetPerson.call(obj2, 'Pavan', 'Varma'); // Ola Pavan Varma

JavaScript uses these tricks, behind the scenes to implement constructor functions.

function Person(firstName, secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
var p = new Person('Pavan', 'Varma');

The new keyword creates a brand new empty object, calls the specified function with this set to that object, and then returns it (You can also see that the function never returns anything).

That’s it regarding this for now, happy coding (-_-).