JS Interview: What is ‘this’?

Matthew Holman
Jul 12 · 5 min read

JS Interview is a series of short articles where we will explore common JavaScript related interview questions. In this article, we will explore what the ‘this’ keyword is and why it’s such a tricky interview question!

What is ‘this’???

Simply Put

In the English language, we use the pronoun ‘this’ to reference something:

I’m going to wear this jacket.

or

This is my computer. There are many like it, but this one is mine.

Similarly, in the JavaScript language, the ‘this’ keyword is used to reference something — an object (don’t forget, in JavaScript, functions are first-class objects).

However, the thing that the ‘this’ keyword is referencing can change based on the execution context and how the ‘this’ keyword was invoked…

Wait a second…

Your ‘this’ keyword reference can change based on many things, including:

And because functions are first-class objects and can be passed around, it can be easy to lose track of exactly what ‘this’ is referring to!

Strict vs un-strict

The ‘this’ keyword can refer to different objects depending if you are operating in ‘strict’ mode or not.

If you were not operating in strict mode and invoked the following function, it would refer to the global object:

function whatIsThis() {
console.log(this);
}

However, if you were in strict mode and invoked the same function, the ‘this’ keyword would be undefined!

Object method

If we create an object with a method, such as:

const myObject = {
greeting: 'Hello darkness my old friend.',
greet: function () {
console.log(this.greeting);
}
};

And then we invoke the method with:

myObject.greet();

The console output would be the greeting we expected:

Hello darkness my old friend.

However, if we were to create a new variable that referenced the greet function of myObject and tried to invoke it:

const greetAgain = myObject.greet;
greetAgain();

The console output would be undefined!

It is undefined because the method is being invoked in the global context, rather than the context of the myObject variable. When it is invoked in the global context, the ‘this’ keyword refers to the global object, rather than our myObject variable.

If we want to get the greeting, we need to add the variable to the global context. If we revise our code to add the greeting variable:

const greeting = "Howdy from Texas!";
const greetAgain = myObject.greet;
greetAgain();

The new console output will be:

Howdy from Texas!

Nested objects

When invoking a method that utilizes the ‘this’ keyword within a nested function, ‘this’ takes the reference of the immediate object calling the function.

If we had the following object:

const parentObject = {
g1: 'Hey, I'm the parent!'
childObject: {
g2: 'Hey, I'm the child!'
makeAnnouncement: function() {
console.log(this.g1 + ' and ' + this.g1);
}
}
};

And invoked the makeAccouncement() method:

parentObject.childObject.makeAnnouncement();

It would output to the console:

 and Hey, I'm the child!

That is because g1 is not available to childObject. There are several ways to bind the parent object variables to the child object, which we will cover later.

Function.prototype.call()

You can invoke a method with .call(). When you do so, it calls the function with a given ‘this’ value and arguments. Invoking a function directly with the parenthesis syntax is the same thing as invoking with .call(). The ‘this’ reference again depends on if you are in ‘strict’ mode or not. If we have the following function:

function greet(person) {
console.log("Hello " + person);
}

Invoking it in strict mode with:

greet("Matthew");

Would be the same as invoking it with the call method with an ‘undefined’ this argument:

greet.call(undefined, "Matthew");

Or calling it in non-strict mode with the window object as the ‘this’ argument:

greet.call(window, "Matthew");

Function.prototype.apply()

You can also invoke a method with .apply(). The apply method is similar to the .call() method, except it accepts a single array of arguments rather than an arguments list.

Function.prototype.bind()

Sometimes you may want to invoke a function and insure it always maintains a particular ‘this’ value. By invoking a method with .bind(), we wrap the original function with a new function that ensures the original function is called with the specified ‘this’ value.

When the code is run below, the printName() function returns “Matthew” because it was invoked at the global scope and the name variable was assigned the value “Matthew” at the global scope:

this.name = "Matthew"; //"Matthew" is assigned to the global object
const person = {
name: "Mark",
age: 21,
getName: function() { return this.name; }
}
const printName = person.getName();
printName();

If we wanted our function to return “Mark”, we could use bind:

this.name = "Matthew"; //"Matthew" is assigned to the global object
const person = {
name: "Mark",
age: 21,
getName: function() { return this.name; }
}
const printName = person.getName.bind(person);
printName();

Object.create()

The Object.create() method creates a new object, using an existing object as the prototype of the newly created object. The object inherits properties from the parent object, so if we were to create a new object from the ‘person’ object above:

const funnyPerson = Object.create(person);
funnyPerson.isFunny = true;
funnyPerson.lastName = "Jefferson"

We can invoke the getName method on the newly created funnyPerson object, and it would inherit the name from the parent object, even though we never explicitly assigned a name to funnyPerson:

console.log(funnyPerson.getName());

and the output to the console would be: “Mark”

The ‘new’ operator

Creating an object with the ‘new’ operator allows it to inherit properties up the parent chain, similar to using Object.create().

Conclusion

There you have it! Easy peasy right? Soooo, if you get asked this question during an interview, feel free to take up the entire allotted time breaking down what the ‘this’ keyword could be referencing in various scenarios. If I helped clear things up, please let me know 👏! If you still have any questions, or if I got something wrong (it happens), let me know in the comments below!

If you enjoyed this article, you may also enjoy some others from the JS Interview series:

JS Interview: Explain Event Delegation

Sources
Vojtech Ruzicka’s Programming Blog
Lets get this `this` once and for all
Understanding JavaScript Function Invocation and “this”
MDN: Object