Sanjucta Ghose
Sep 11 · 5 min read
Photo by Lance Grandahl on Unsplash

The this keyword is kind of confusing in Javascript. If you come from languages like Java or C++, you would think a ‘this’ reference within a method would unambiguously mean the object within which the method is defined. Not so in Javascript. Lets look at some code to see what I mean.

function Person(firstName,lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.getName = function()
{
return this.firstName + " " + this.lastName;
}
var jim = new Person("Jim","Kerry");console.log(jim.getName());var nameFunc = jim.getName;console.log(nameFunc());

The output for the above code block is

'Jim Kerry'
'undefined undefined'

The first ‘console.log’ prints ‘Jim Kerry’ as expected. But if you assign the getName function to another variable(which is something which Javascript allows since funtions are first-class objects ) and invoke the function using that variable, then this.firstName and this.lastName are undefined. This is so because Javascript resolves the ‘this’ reference based on how the function is invoked. Since nameFunc in the snippet above is not invoked ‘on’ any object, Javascript resolves the ‘this’ reference to the global object (the window object if the code is running in the browser).

You might wonder why one would want to assign a method to some other variable and then invoke it. Lets look at another (rather contrived) example.

Suppose we had a function constructor to create objects that represent salads.

function SaladIngredients(vegetables,dressings)
{
this.vegetables = [];
this.dressings = [];for (vegetable of vegetables)
{
this.vegetables.push(vegetable);
}
for (dressing of dressings)
{
this.dressings.push(dressing);
}

}
SaladIngredients.prototype.addVegetables = function()
{
console.log("Adding vegetables");
console.log(this.vegetables);
}
SaladIngredients.prototype.addDressings = function()
{
console.log("Adding dressings");
console.log(this.dressings);
}

So to make a salad we could write something like

var tomatoAndCheeseSalad = new SaladIngredients(['tomatoes','cheese','lettuce'],['olive oil','vinaigrette']);tomatoAndCheeseSalad.addVegetables();
tomatoAndCheeseSalad.addDressings();

And the output would be

'Adding vegetables'
(3) [
"tomatoes",
"cheese",
"lettuce"
]
'Adding dressings'
(2) [
"olive oil",
"vinaigrette"
]

Now suppose I wanted to write a general function to make different kinds of salads without having to call the methods addVegetables and addDressings again and again. I could write a function like this

function foodMaker(saladIngredients)
{
var steps = [];
for(var member in saladIngredients)
{
if(typeof(saladIngredients[member]) === 'function')
steps.push(saladIngredients[member]);
}
for(step of steps)
{
step();
}

}

This function takes a SaladIngredients object and calls all the methods on it to prepare a salad. So to make a salad I could write

var salad1 = new SaladIngredients(['tomatoes','cheese','lettuce'],['olive oil','vinaigrette']);foodMaker(salad1);

But my output this time would not be what I expected.

'Adding vegetables'
undefined
'Adding dressings'
undefined

Since the ‘step’ function is not called ‘on’ any object, Javascript assumes that the ‘this’ reference inside the addVegetables and addDressings methods refer to the global object which does not have ‘vegetables’ or ‘dressings’ properties.

To get around this, Javascript provides the methods bind, call and apply. The call and apply functions are simply different ways in which to call a function. So given a function

function addNumbers(num1,num2)
{
return num1 + num2;
}

we could call it in one of the following 3 ways

addNumbers(4,5);
addNumbers.call({},4,5)
addNumbers.apply({},[4,5])

All 3 function calls would return 9.The first parameter passed to call or apply is an object to which Javascript resolves the ‘this’ reference within the function. The subsequent parameters are the actual arguments in the case of call and an array containing the actual arguments in the case of apply. Let’s see how this works with a function that has a ‘this’ reference within it.

function printMultiplied(multiplier)
{
console.log(this.value*multiplier);
}
printMultiplied(2);
printMultiplied.call({value:2},2);
printMultiplied.apply({value:2},[2]);

The output of the above snippet is

NaN
4
4

The first call to printMultiplied returns NaN because ‘this.value’ is undefined as ‘this’ resolves to the window or global object which does not have a property called ‘value’. In the subsequent 2 calls however, we have passed as the first parameter, an object that contains a value property and Javascript engine is able to resolve this.value to the value 2.

Armed with this knowledge, we could rewrite our foodMaker function like this using ‘call’

function foodMaker(saladIngredients)
{
var steps = [];
for(var member in saladIngredients)
{
if(typeof(saladIngredients[member]) === 'function')
steps.push(saladIngredients[member]);
}
for(step of steps)
{
step.call(saladIngredients);
}

}

Now a call to

foodMaker(new SaladIngredients(['tomatos','lettuce'],['olive oil']));

would yield

'Adding vegetables'
(2) [
"tomatos",
"lettuce"
]
'Adding dressings'
(1) [
"olive oil"
]

Now let’s talk about what the bind method does. The bind method does not invoke a function. It returns another function with the same body as the one it is invoked on but with the ‘this’ reference locked down to the object that is passed to it. Let’s look at some code

function printMultiplied(multiplier)
{
console.log(this.value*multiplier);
}
var printMultipliedBy2 = printMultiplied.bind({value:2});printMultipliedBy2(3);
printMultipliedBy2(4)

The output of the above code is

6
8

We call the bind method on the ‘printMultiplied’ function passing it an object which contains a property called ‘value’. The Javascript engine returns a new function within which ‘this’ will always point the object that we passed in to bind, no matter how the function is invoked. This becomes clearer if we look at the code below :

function printMultiplied(multiplier)
{
console.log(this.value*multiplier);
}
var printMultipliedBy2 = printMultiplied.bind({value:2});var a = {
value : 3
}
a.func = printMultipliedBy2;a.func(2)

The output of the above snippet is

4

Although we are assigning printMultipliedBy2 to a property ‘func’ of the object ‘a’ which itself has a property called ‘value’ with a value 3, within the call to a.func, ‘this.value’ still resolves to 2 .

Using bind we can rewrite ourfoodMaker’ function like this.

function foodMaker(saladIngredients)
{
console.log("Here1");
var steps = [];
for(var member in saladIngredients)
{
if(typeof(saladIngredients[member]) === 'function')
steps.push(saladIngredients[member].bind(saladIngredients));
}
for(step of steps)
{
step();
}

}

To summarize,

  • Javascript resolves the this keyword within a function depending on how the function is invoked
  • You can use call or apply to invoke a function passing in an object to which the Javascript engine will resolve any this references within the function call
  • You can use bind to lock down the this reference in a function to whatever object to pass in when you invoke bind

brandsoft

A Technology Publication

Sanjucta Ghose

Written by

brandsoft

brandsoft

A Technology Publication

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade