Javascript: What’s `this`?

Michael Ries
Code Monkey
6 min readOct 22, 2017

--

Many new Javascript developers — and even many that are not so new — struggle to know what this is at some point in their program. Often we learn self (eg. ruby) or this (eg. Java) in classical languages, and in those languages the behavior is predictable. It always refers to the current object, which is an instance of a class. In Javascript however, the value of this behaves differently, sometimes behaving like you expect, and sometimes behaving in unexpected ways.

Allow me to demonstrate what I mean with a few examples.

Let’s make a very simple object with method:

const xena = {
attack: function() {
console.log(`Xena swings her ${this.weapon} at the foe!`)
}
}
xena.attack(); // Xena swings her undefined at the foe!

This behavior isn’t too surprising, because Xena has no weapon. So let’s give our brave warrior princess a weapon.

xena.weapon = 'Sword';   // let's give her a weaponxena.attack();   // Xena swings her Sword at the foe!

Much better! If we console.log(xena)we see

Xena has a weapon and an attack method

So far, this works exactly as we might expect based on our experience with classical languages. Now, let’s imagine that we want our fighter to attack when we click an attack button on the page. To keep the example simple, let’s add our click event listener to the document object.

document.addEventListener('click', xena.attack)
// (Upon clicking the page) Xena swings her undefined at the foe!

Wait, what? That’s not what we wanted! What happened?

The execution context

Remember that in classical languages, this refers to an instance of a class. In javascript, we don’t have classes, although we sometimes mimic them with prototypal inheritance. So what should this reference?

Just like in the English language, the word this is useless without some context. If you are listening to music with your headphones and you say to me, ‘I don’t like this song’, it will be meaningless to me because I don’t know what song you are listening too. That is, I don’t know the context in which you are saying this. Javascript works the same way. The value of this depends on the execution context of the calling function, rather than anything to do with the object.

In Javascript, the value of `this` depends on how it was called (the execution context), and not what object it is contained within.

Gabrielle arrives on the scene just in time to give Xena some much-needed assistance. We create a gabrielle object just like our xena object, but we don’t want to duplicate the code for the attack method, so we extract it.

const attack = function() {
console.log(`${this.character} swings her ${this.weapon} at the foe!`)
}
const xena = {
character: 'Xena',
weapon: 'Sword',
attack: attack
}
const gabrielle = {
character: 'Gabrielle',
weapon: 'Staff',
attack: attack
}
// in this case, this refers to xena
xena.attack(); // Xena swings her Sword at the foe!
// but here, it refers to gabrielle
gabrielle.attack(); // Gabrielle swings her Staff at the foe!
// and what if we call attack() directly?
attack(); // undefined swings her undefined at the foe!

This example demonstrates how the value of this inside of the attack function cannot be known without considering how the function is being called.

As a general rule, the value of this will be the object that the method was called on; that is, the object to the left of the dot. If the function is not called on an object, then this will usually be the global object (the window, in the case of a browser) or undefined if running in strict mode. This is is true even when the method to be called is not on the object itself and is instead on the prototype chain.

Binding

There are often times when we don’t know or have direct control over how a function is going to be called. It is very common in Javascript to pass functions as parameters to other functions. When we do, the functions are passed as objects and they lose their connection to their execution context.

Remember what happened when when we tried to get Xena to attack when we clicked on the webpage? It turns out that with event handlers, the value of this will reference the object that fired the event — the document object, in our example. This can be very useful when the same event handler is used to handle events from many possible sources, such as buttons on a page.

In other cases, we don’t always know what this is going to reference, or it may not be useful to us. Sometimes we need to specify what we want this to be when a function is called, regardless of the execution context. Javascript provides the bind method to solve this problem.

The bind method creates a new function that will always have this set to the first argument you provide. So if we call addEventListener() a little differently, we get the desired behavior.

document.addEventListener('click', xena.attack.bind(xena))
// (Upon clicking the page) Xena swings her Sword at the foe!

Now, when the event fires and the handler is called, the value of this is xena because the function we passed was bound to the xena object.

You could even do some suspicious things (don’t do this):

xena.attack = attack.bind(gabrielle);
xena.attack() // Gabrielle swings her Staff at the foe!

Call and Apply

The bind method creates a new function with a predetermined this but it doesn’t execute immediately. Sometimes you want to specify what this will be when you are calling a function. For this purpose you would use the call or apply methods. Since these methods behave almost identically, I’ll just demonstrate call.

When you use call you are calling the function normally, except that you are telling the function what to use for this. For example:

attack.call(xena);       // Xena swings her Sword at the foe!
attack.call(gabrielle); // Gabrielle swings her Staff at the foe!

The call methed accepts additional arguments that will be passed through to the function being called, but the first argument is the one that will be used for this. If we were to change our attack function a bit to accept a target:

const attack = function(target = 'foe') {
console.log(`${this.character} swings her ${this.weapon} at the ${target}!`)
}
attack.call(xena, 'evildoer')
// Xena swings her Sword at the evildoer!

Arrow Functions

Arrow functions (created using =>) behave differently than those defined using the function keyword. Arrow functions bind this to the enclosing context when they are created, and it cannot be changed. So for example if we replace Gabrielle’s attack function with an arrow function, we cannot get it to work the way we want.

const attack = function(target = 'foe') {
console.log(`${this.character} swings her ${this.weapon} at the ${target}!`)
}
const attackArrowFunction = (target = 'foe') => {
console.log(`${this.character} swings her ${this.weapon} at the ${target}!`)
}
// the value of `this` inside attackArrowFunction is already set
// to the global object
const xena = {
character: 'Xena',
weapon: 'Sword',
attack: attack
}
const gabrielle = {
character: 'Gabrielle',
weapon: 'Staff',
attack: attackArrowFunction
}
xena.attack() // Xena swings her Sword at the foe!
gabrielle.attack() // undefined swings her undefined at the foe!
gabrielle.attack.call(gabrielle) // undefined swings her undefined at the foe!
gabrielleAttack = gabrielle.attack.bind(gabrielle);
gabrielleAttack(); // undefined swings her undefined at the foe!

The `new` keyword

When calling a constructor function using new the value of this is set to the object that is being created.

const Warrior = function(name) {
this.character = name, // `this` references the object
this.weapon = 'Sword' // that is being created and
this.attack = attack // will be returned by the function
}
const ares = new Warrior('Ares');
ares.attack('warrior princess'); // Ares swings her Sword at the warrior princess!

Note that you cannot create a constructor function with =>.

Parting Words

The concept of this in Javascript is probably the most difficult thing to learn and master, but it’s important to understand.

If there was anything you read here that has you confused, please feel free to post your questions below and I’ll try to clarify.

If you like what you read, throw a few claps my way so that this story will reach others who may benefit.

Finally, please checkout my related earlier stories.

Object Composition in Javascript

Javascript ‘Classes’ and Prototypal Inheritance

Understanding Closures in Javascript

Resources

--

--

Michael Ries
Code Monkey

Solving complex problems one simple problem at a time.