What is THIS
If the function is defined as an arrow function: #
In this case, the value of this
is always the same as this
in the parent scope:
Arrow functions are great because the inner value of this
can't be changed, it's always the same as the outer this
.
Other examples #
With arrow functions, the value of this
can't be changed with bind
:
With arrow functions, the value of this
can't be changed with call
or apply
:
With arrow functions, the value of this
can't be changed by calling the function as a member of another object:
With arrow functions, the value of this
can't be changed by calling the function as a constructor:
'Bound' instance methods #
With instance methods, if you want to ensure this
always refers to the class instance, the best way is to use arrow functions and class fields:
This pattern is really useful when using instance methods as event listeners in components (such as React components, or web components).
The above might feel like it's breaking the "this
will be the same as this
in the parent scope" rule, but it starts to make sense if you think of class fields as syntactic sugar for setting things in the constructor:
Alternative pattens involve binding an existing function in the constructor, or assigning the function in the constructor. If you can't use class fields for some reason, assigning functions in the constructor is a reasonable alternative:
Otherwise, if the function/class is called with new
: #
new
: #The above will call Whatever
(or its constructor function if it's a class) with this
set to the result of Object.create(Whatever.prototype)
.
The same is true for older-style constructors:
Other examples #
When called with new
, the value of this
can't be changed with bind
:
When called with new
, the value of this
can't be changed by calling the function as a member of another object:
Otherwise, if the function has a 'bound' this
value: #
this
value: #Whenever boundFunction
is called, its this
value will be the object passed to bind
(boundObject
).
Warning: Avoid using bind
to bind a function to its outer this
. Instead, use arrow functions, as they make this
clear from the function declaration, rather than something that happens later in the code.
Don't use bind
to set this
to some value unrelated to the parent object; it's usually unexpected and it's why this
gets such a bad reputation. Consider passing the value as an argument instead; it's more explicit, and works with arrow functions.
Other examples #
When calling a bound function, the value of this
can't be changed with call
or apply
:
When calling a bound function, the value of this
can't be changed by calling the function as a member of another object:
Otherwise, if this
is set at call-time: #
this
is set at call-time: #The value of this
is the object passed to call
/apply
.
Warning: Don't use call
/apply
to set this
to some value unrelated to the parent object; it's usually unexpected and it's why this
gets such a bad reputation. Consider passing the value as an argument instead; it's more explicit, and works with arrow functions.
Unfortunately this
is set to some other value by things like DOM event listeners, and using it can result in difficult-to-understand code:
Don't
I avoid using this
in cases like above, and instead:
Do
Otherwise, if the function is called via a parent object (parent.func()
): #
parent.func()
): #In this case the function is called as a member of obj
, so this
will be obj
. This happens at call-time, so the link is broken if the function is called without its parent object, or with a different parent object:
someMethod() === obj
is false because someMethod
isn't called as a member of obj
. You might have encountered this gotcha when trying something like this:
This breaks because the implementation of querySelector
looks at its own this
value and expects it to be a DOM node of sorts, and the above breaks that connection. To achieve the above correctly:
Fun fact: Not all APIs use this
internally. Console methods like console.log
were changed to avoid this
references, so log
doesn't need to be bound to console
.
Warning: Don't transplant a function onto an object just to set this
to some value unrelated to the parent object; it's usually unexpected and it's why this
gets such a bad reputation. Consider passing the value as an argument instead; it's more explicit, and works with arrow functions.
Otherwise, if the function or parent scope is in strict mode: #
In this case, the value of this
is undefined. 'use strict'
isn't needed in the function if the parent scope is in strict mode (and all modules are in strict mode).
Warning: Don't rely on this. I mean, there are easier ways to get an undefined
value 😀.
Otherwise: #
In this case, the value of this
is the same as globalThis
.
Last updated