JavaScript This Walkthrough
Last updated
Last updated
Understand how this
depends on the invocation of a method
this
JavaScript's this
keyword can sometimes be unpredictable. Now that we are going deeper into object oriented code, we should discuss it with the detail that it deserves. In brief, the value of this
changes based on where it is.
Outside of any function, this
refers to the . In web browsers, this is the
Inside an object method, this
refers to the object that received the method call
Inside a standalone function, this
will either default to the or be undefined
Let's make sure we properly define the word method. A JavaScript method is a property on an object that points to a function. So just like we can write let person = {name: 'bob'}
, whereby the name
property points to a value of 'bob'
, we can also write the following:
And have the greet
property point to a function. Because this greet
property points to a function, we call the property a method. Ok, so because the greet
property is a method, we know that when we call person.greet()
the object receiving the method call equals person
. Let's modify our greet
function and see that:
We see that person.greet()
returns this
, which refers to the object that received the method call.
this
ChangeOk, hang on tight, because we are about to see something weird. Let's modify the code above slightly:
Ok, so let's walk through the code above. We set our greet
property on the person
object to point to the same function, and see that when we call person.greet()
, this
refers to the person
object.
The tricky part happens when we write let greetFn = person.greet
. What this does is assign a local variable greetFn
to refer to the function on the person
object. However, this local variable does not refer to the person
object at all. It has zero knowledge of the person
object. It only points to the function. Then we invoke the function by calling greetFn()
. In doing so, we are not calling the property on the object, we are simply invoking the function.
When the function is invoked, this
refers to window
, our global object.
Another occurrence where this
becomes the global object is when we invoke functions within functions. Let's change our code to look like the following:
Ok, let's walk through what the above code is doing. Our object, person
has a property greet
that contains to a function. Now when this method, greet
, is called, it first declares and then invokes the otherFunction
function. The otherFunction
returns this
, which is then returned by the greet
method. So what does this
equal? Well, note that this
is not referenced directly inside a method. otherFunction
is not a method, just a function.
Remember, a method is a property that points to a function. If we call the person.greet
property, it invokes an anonymous function. That function is in the context of person
. The function it contains, otherFunction
, is not.
With the exception of arrow functions, every time a function is invoked, this
will be defined based on the context that it is in. Inside otherFunction
, this
defaults to the global object.
The previous example may seem unnecessarily complicated, but we actually include functions in other functions whenever we use callbacks. In fact, many out of the box JavaScript functions are passed callbacks. So if we did something like the following:
Each time our callback function is invoked, this
is global. Do you see why? Our function is invoked by the filter
method. Filter is a method. We can invoke it as a property on our array. However, the callback function is not called as a property on an object, and thus when we reference this
from inside the callback function, this
will refer the window, or global object.
Arrow functions do not have their own this
. Instead, an arrow function uses whatever this
is defined within the scope it is in. So, for instance, if we rewrote our last person
object:
The arrow function assigned to otherFunction
(inside of greet
) uses this
from the person
object. otherFunction
does not have its own this
, so it defaults to using this
from the scope it is in. The result is that this
will now refer to person
.
Inside innerFunction
, this
has defaulted back to undefined, as it does with normal functions. Once again, though, with an arrow function, this
will not be redefined, so we could rewrite the code as follows:
Now, the this
inside of innerFunction
will be based on the context the arrow function is in: the greet()
method. Inside the greet()
method context, this
will refer to the object it is in: Person
.
The above lesson displayed how this
changes depending on how a function is called and where that function is. We can make an addendum to our original rules about this
:
Inside an object method, this
refers to the object that received the method call
Arrow functions don't define their own this
like standard functions do.
We saw that even if a function was originally declared as a property on an object, if we do not reference the function as a method, this
will default to the global object.
We also saw how callback methods are a specific application of an inner function being called, and therefore this
again defaults to the global object.
this
has some specific behaviors that can sometimes lead to unexpected results. In later lessons, we will look at some built in JavaScript methods that actually allow us to control what this
refers to, ensuring that when we fire a function, it will always be in the right context.
Methods defined within behave similarly. If we were to rewrite our person
object into a class:
Outside of any function, this
refers to the . In web browsers, this is the
Inside a standalone function, even one inside a method, this
will default to the
When using in a standalone function, as we do inside classes, this
will be undefined