this
keyword. Now, it is common in other languages too but it’s a little different in JavaScript. This is one of the fundamental topics but still unclear for many. This topic is a bit long, but trust me you will have a better picture when you reach the end of this article.The this
keyword is a special property of an execution context(in layman’s terms — environment a function executes in). The context could be global, a function or eval. The value this
is determined by how a function is called, not when/where it was defined.
Contents
Global context – this keyword
Outside of any function is the global environment.
this
refers to the global object. So what happens if we log this
in our console? Guess before you find out from the example.When this
is referred in our console, it logged the window object which is the global object for web browsers.
Function context – this keyword
Inside a function, the value of
this
depends on how the function is called.
Simple Call
Invoking this
from a function refers to the context in which the function is called. Consider the below example:
The function foo
is called in a global context. Hence, the window object is printed.
As an Object Method
When a function is called as a method of an object, its
this
is set to the object the method is called on
What just happened?! Did you notice how the context within the function is not affected by how or where the function was defined?
No matter if the function is defined inline like bar
or defined first and later attached to obj
as in baz
the result is the same. As discussed, what matters is how the function was invoked. Hence, the context in bar
and baz
refer to the object property a
and not the global variable a
.
Checkout my previous article on Google DevTools’ console tips that would change your debugging experience
Context in Event handlers
We are all familiar with event-handlers like onclick
, where we have access to the DOM element using $(this)
,e.target
or e.currentTarget
when clicked. This is nothing but using context on “click” event to manipulate the DOM data.
As DOM event handler
When a function is used as an event handler, its
this
is set to the element on which the listener is placed.
As Inline event handler
When the code is called from an inline event handler, its
this
is set to the DOM element on which the listener is placed.
In the above example, we can change the colour of the text in the first div
. But the same won’t be possible with the second div
because the inner function’s this
isn’t set so it returns the global/window object.
As a constructor
When a function is used as a constructor (with the
new
keyword), itsthis
is bound to the new object being constructed.
Observe how the context is set to the new object created using new
:
Changing context explicitly
Now that we have seen how a context is set based on how a function is called, let’s move on to see the ways we can change the context explicitly. Yes, we do have control over setting the context for a given function.
1. Using ‘strict'
In strict mode if the value of
this
is not set when entering an execution context, it remains asundefined
In the first example, calling this
insidefoo
is undefined
, because foo
was called directly and not as a method or property of an object.
2. Using bind
The
bind()
method creates a new function that, when called, has itsthis
keyword set to the provided value.
It simply means that using bind
on a function will return a new function, which behaves the same as the function on which .bind
was called on, only that the context is set by us.
Now, do you understand why we bind event-handlers in React components?
If you forget to bind event methods and pass it to the event, this
will be undefined
when the function is called. Hence,setState
won’t be accessible. Next time you find it annoying, don’t blame React 😂
Note: We can also use apply()
and call()
which are similar in functionality. The difference is bind()
executes the function later but apply()
and call()
executes it immediately.
3. Arrow functions
In arrow functions,
this
retains the value of the enclosing lexical context’sthis
.
What does that mean? We have seen so far that the context depends on how the function is called and not where or when it is defined. Well, with arrow functions this can be changed and the function retains the context in which it was defined. See the example below:
Notice how obj.bar()
retains the global context.
Though arrow functions are used for its clean syntax, it is a popular way to set the context to parent function in callbacks.
Note: The arrow functions are immune to bind, call and apply too.