The this
keyword in JavaScript can cause a lot of headache if you aren’t sure what it references.
A function’s this
references the execution context for that call, which is determined by how the function is called. This is the golden rule that will help you resolve the this
value in any function.
Functions can be called in four different ways in JavaScript:
- Implicit Binding
- Explicit Binding
- The
new
keyword - Default Binding
Let’s explore each of them.
Implicit Binding
The this
keyword in a function refers to the object that invokes that function.
|
|
In this example, this
references classroom
, so this.teacher
resolves to classroom.teacher
which resolves to Eric
.
This allows us to pass in function definitions to different objects and have the objects use the function in their context.
|
|
Explicit Binding
You can also set the this
context when invoking a function using the call
, apply
, or bind
method.
Using the call or apply Method
|
|
When we are passing in the classroom1
and classroom2
objects to the call
method, we are explicitly telling the remark
function to use the objects as the this
value inside the function.
Note: The apply
method works similarly except it takes in the function arguments as an array instead of a comma separated list.
Using the bind Method
|
|
The bind
method makes a copy of the function that calls it, sets its this
context to the object that is passed in, and returns the new function.
Every time that bound function is called, it’ll have its this
permanently set to the object with which bind
was called.
Notice how calling setTimeout
with classroom.say
doesn’t work as the function remark
will be called by the window
object which doesn’t have any teacher
variable defined on it.
But when it’s called with the boundRemarkFunction
, it works because the this
keyword in the function will always reference classroom
.
The new Keyword
|
|
The new
keyword is used for constructor calls. This allows us to link multiple objects to the same function through their prototype chain.
The new
keyword does four things:
- Creates a new empty object .
- Links the newly created object’s
__proto__
to the function’s prototype. - The new object is set as the
this
reference for that function call. - Returns the newly created object automatically unless there is an explicit
return
statement inside the function.
Here’s what it’d look like if you were to use Object.create
to link the functions:
|
|
Default Binding
What happens when none of the above rules apply?
In non-strict mode, the fallback is defined as the global object.
In strict mode, this
is set to undefined.
|
|
The teacher
variable is declared as a property on the window
object. When remark
is called, this.teacher
evaluates to window.teacher
which evaluates to "Eric"
.
Note that this won’t work if teacher
is declared with either let
or const
(see here for the reasons).
What happens in Arrow Functions?
The rules mentioned above don’t work in arrow functions. These functions instead use the this
reference of the function they are enclosed in.
|
|
In the classroom1
, when we call createRemarkArrowFunc
the value of this
defaults to window
according to the default rule. Since we don’t have any teacher
variable defined globally, this.teacher
evaluates to undefined
.
For the classroom2
object’s say
property, we explicitly set the this
to the classroom2
object when calling createRemarkArrowFunc
. The this.teacher
inside the arrow function evaluates to classroom2.teacher
which then evaluates to Otha
.
Note that the behavior of arrow functions can’t be overridden even by the new
keyword.
Read the “Lexical this
” section here for more details.