The THIS Keyword¶
As you know, the this keyword in JS OOP refers to the current object
within a constructor or a method. In this reading, we'll look at a few
surprising and subtle aspects of this, but we're not going to cover
every quirk of it. If you want to know more about
this
you can explore more in that link.
Changeability¶
An important thing to keep in mind about this is that it's
constantly changing. Every time there's a function call or a method
call or an object construction, the value of this changes. Most of
the time, the new value is either irrelevant or exactly what you
want. So, there's no cause for alarm.
Constructor¶
If we use a constructor
var harry = new Account(50);
Then the value of this in the body of the constructor function is
the new object (the one that will be assigned to harry above):
class Account {
// our instance variable
balance = 0;
// the value of `this` is the new object
constructor (init) {
this.balance = init;
}
}
That's exactly what we want.
Methods¶
If we use a method
harry.deposit(100);
then the value of this in the body of the method is the object that
the method is operating on:
class Account {
// our instance variable
balance = 0;
constructor (init) {
this.balance = init;
}
// the value of `this` is the object to work with
deposit (amt) {
this.balance += amt;
}
}
Again, this is exactly what we want.
Methods are Functions¶
So far, we've only invoked methods. The dot syntax, though, allows us to pull a value out of an object, and a method is a value in an object (kinda — there's a subtlety here that we can skip for now). Return to our bank page and try the following code:
harry.balance;
harry.deposit;
Here's a screenshot of how it worked for me:

So, deposit is a kind of function, but a function stored in an
object. Actually, to be precise, the function is stored in something
called a prototype, which all instances of a class have access
to. That means that Harry's deposit method is the very same function
as Ron's and Hermione's deposit methods. But prototypes are not a
source of concern.
Stripped to its essentials, the deposit method (all of them; they're
all the same) is:
function (amt) {
this.balance += amt;
}
So, it will work fine as long as there's a value for this.
As you know, when we use the method properly, the value of this is
set correctly:
ron.deposit(10);
Remember, a method is just a function that belongs to a particular
class of object, like deposit and withdrawal belong to
Account.
Methods as Arguments¶
But we know from earlier work (such as the Plotting assignment) that
functions can also be arguments, as with the .map() and .forEach()
methods.
Suppose a group of friends decides to help Ron out, passing the hat to collect money for him (maybe to go home for the holidays or to get a new broom or dress robes). We could implement code like this:
console.log(ron.balance);
var hat = [10, 20, 30, 40]; // total of 100
hat.forEach(function (amt) { ron.deposit(amt) });
console.log(ron.balance);
This works spectacularly well. (You can copy/paste that code into the console for the bank page and test it. Ron's balance increases by 100.)
But note that the argument to forEach above is an ordinary function, not
a method. What if it were a method? Try the following:
console.log(ron.balance);
var hat = [10, 20, 30, 40]; // total of 100
hat.forEach(ron.deposit);
console.log(ron.balance);
That fails. It fails because the value of this is incorrect. But
the earlier code with the anonymous function works fine, so let's
stick with anonymous functions.
Functions inside Methods¶
In fact, we decide to get ambitious. We decide that the passing the
hat
code is useful and generic, and it might be nice to have a
method that makes a bunch of deposits into a bank account. Here's our
attempt:
class Account {
...
depositAll (hat) {
hat.forEach(function (amt) { this.deposit(amt) });
}
...
}
Try it out at account2 with code like:
console.log('before', ron.balance);
ron.depositAll([1,2,3,4]);
console.log('after', ron.balance);
The code fails because the anonymous function (the argument to
forEach) doesn't have the correct value for this. A named function
would fail for the same reason. Both would fail because the function
is called (by .forEach) as an ordinary function, not as a method,
and ordinary functions get a different value for this. (The value
it gets varies depending on JavaScript implementation and context, but
it's never the right value. In a browser, it's the global object,
which we met as globalThis.)
Arrow Functions as a Solution¶
There are many solutions, but the easiest is to use an arrow function instead of a normal function.
Remember that an arrow function, in it's most concise form, consists of a parameter list, an arrow, and an expression. For example:
xValues = [1, 2, 3, 4];
doubles = xValues.map(function (x) { return x*2; });
triples = xValues.map( x => x*3 );
You can see that the arrow function is much more concise. (If we have
multiple parameters, we use parentheses around them, and if we have a
multi-statement function body, we surround it with braces and bring
back the return keyword, if necessary.)
When we learned about arrow functions, we only learned about them as a concise alternative to normal functions, but there also are a few technical differences between them and normal functions:
- Invoking a normal function changes
this - Invoking an arrow function does not change
this
Note that the second fact means that we cannot use arrow functions
as methods. But we can use them inside methods! So, we can change
the depositAll method to the following:
class Account {
...
depositAll (hat) {
hat.forEach(amt => this.deposit(amt));
}
...
}
It works! The this inside the arrow function is the same value it
normally has in the method, which means it still correctly refers to
the bank account.
Try it out at account3 with code like:
console.log('before', ron.balance);
ron.depositAll([1,2,3,4]);
console.log('after', ron.balance);
Other Solutions¶
The arrow function solution is simple and effective. It's really all
you need. However, before we drop the subject, let's look at two other
ways to solve it: bind and closures. (If your brain is full, you can
stop here. This section is optional.)
For the purpose of this problem discussion, let's use our bank account example as a concrete case, and then we'll describe it more generally. You can try the example code using
The depositAll method takes an array as an argument (a "hat") and
deposits all the amounts in the hat into the given bank
account. Pretty cool, but a little inflexible. Suppose we wanted a
function, taking one argument (an amount of money) and invoking the
function deposits that money in the given bank account. Let's call
that a depositor function.
Arrow functions are one way to create a depositor function:
const d1 = amt => ron.deposit(amt);
d1(10); // ron is 10 galleons richer
So, as we said, an arrow function solves the problem. Remember that the function/method itself does not solve the problem:
const d2 = ron.deposit;
d2(10); // gets an error
which results in the following error:

The failure is because the value of this is undefined or unbound,
so I'm going to call the problem the "unbound this" problem.
Another solution is to use the bind method, which specifies a value
to use for this. Consider the following, which works:
const d3 = ron.deposit.bind(ron);
d3(30); // ron is 30 galleons better off
That may seem redundant, but remember that all the methods live in the
prototype object which is accessible from the class constructor
function, so the following means exactly the same thing but doesn't
look as confusing:
const d4 = Account.prototype.deposit.bind(ron);
d4(40);
In short, the bind method takes a method (like deposit), which can
work for any object (of the right class) by operating on the this
keyword, and returns a new function that has a specified, fixed
(constant) value for this. In the example above, d4 is a new
function that will always deposit into Ron's account.
Prior to bind and arrow functions being introduced into the JS
language, programmers ran into the "unbound this" problem. They solved
it by using closures. Basically, the value of this constantly
changes, so they copied the value they wanted to a new variable, and
returned a closure over that value. Traditionally, the variable was
named that.
Before showing you the closure solution, I'm going to define a variant
of our Account class that has methods that return depositor
functions. Remember, the depositor function is a pure function (not a
method) that we could, for example, use with forEach or map or
just by themselves, as we did with d1, d3 and d4 above.
The complete code is in account4.js and you can try it in account4.html. Here's an excerpt:
class Account {
// instance variables
balance = 0;
constructor (init) {
this.balance = init;
}
deposit (amount) {
this.balance += amount;
}
// the depositAll method works
depositAll (hat) {
hat.forEach(amt => this.deposit(amt));
}
// return a depositor function
getDepositor_arrow() {
return amt => this.deposit(amt);
}
getDepositor_bind() {
return this.deposit.bind(this)
}
getDepositor_that() {
let that = this;
return function (amt) { that.deposit(amt) }
}
} // end class
Let's try it out. The solution using arrow functions works:
d5 = ron.getDepositor_arrow();
d5(50); // 50 galleons richer
The solution using .bind also works:
d6 = ron.getDepositor_bind();
d6(60);
Note that the code for depositor_bind is a little confusing, because
there are two uses of this:
getDepositor_bind() {
return this.deposit.bind(this)
}
The first retrieves the method from the prototype, and the second is
the argument to bind. Since the latter is the same as ron, the
depositor function deposits into Ron's account.
Finally, there's a solution that uses a closure over that. It also works:
d7 = ron.getDepositor_that();
d7(70); // richer and richer
The code is simple but not obvious:
getDepositor_that() {
let that = this;
return function (amt) { that.deposit(amt) }
}
We copy the value of this to a new variable, that and then return
a closure over that variable. Skipping the copy and just returning a
function referring to this would not work, as we saw near the
beginning of this reading. (The first time I saw that used as we did
here, I was quite baffled. Fortunately, I understood about closures,
so I was able to figure it out.)
Which technique should you use? Let's briefly summarize:
- arrow: yes, you should use this. It's simple and effective.
bind: you can use this. It has the advantage about being clear about what's going on, namely that you are binding the value ofthis. But you should probably stick to the arrow function.that: this is interesting to know about, and you might encounter it in old (pre-2009) code, but otherwise it's only for historical interest.
Summary¶
- Most of the time,
thishas exactly the value you need - Anonymous functions inside methods might not have the correct value for
this - Invoking an arrow function doesn't change the value of
thisso they are a better choice inside a method - Arrow functions cannot be methods, because invoking them doesn't
change the value of
this