JS : What’s `this` about ?
Well, this is precisely about this
! So let’s begin! And hopefully by the end of this blog you’ll stop using var that = this;
and would have better ways to tackle this problem! 😛
First, let us understand how JavaScript works giving you an abstract idea about the concept of this
. JavaScript is run in an environment which is able to compile your source code, it could be a browser or it could be a node.js environment. Each have what we can call a Global Object, which provides us the variables and functions we use in our code.
To differentiate, the global object in a browser environment is the window
object, (and global
in a node.js environment), so if you just execute
console.log(this) // this === window
In ‘strict mode’:
this
is undefined
in a function invocation in strict mode. However, using strict mode
on a global context is still the window
object.
Back to ‘non strict mode’ :
Any variable that you declare this way :
This, gives you an idea of the JavaScript environment, which is in itself a large object exposing all the methods you need!
NOTE:
Changing var
to ( let
or const
) doesn’t create properties of the window object when declared globally. i.e :
So, basically the idea is
this
points to the enclosing execution context and in case of functions ifthis
is used within them, it depends on the object instance.
Lets understand this with an example :
Meaning, this
is purely based on the execution context of the function. (where as in other programming languages this
refers to the current instance of the class. And, so it doesn’t matter where the function is defined in the code but where is it called. (this changes when using arrow functions, you’ll see why)
But, all these examples look pretty straightforward don’t they? So, where exactly is the problem here ?
The problem arises when you use functions like setTimeout
or inner/nested
functions.
Lets look at an example :
Wait, whaaaaat!? But, isn’t this
being used inside the obj
object? Then why is this.prop === undefined
… hmmm 🤔
Lets, try to debug the problem here!
Case 1: (using setTimeout
)
You might be getting a faint idea of what’s exactly happening here, you can see suddenly inside the setTimeout callback this
points to something else within the callback function.
this
inside the setTimeout
callback points to the window
object instead of obj
object.
But, why is that so and how can we correctly use this
in such cases?
Since, we all know setTimeout
is not a JavaScript (language) feature but a method exposed by the environment (browser) itself. Meaning you can also invoke setTimeout as window.setTimeout(callback, time)
, thereby meaning our callback function is called in the execution context of the global environment (window).
Case 2: (Using inner/nested
functions)
What does “no explicit this
set” mean ?
When you call a function obj.f()
this
is set to obj as we explicitly set the execution context of function f()
to be obj
. But, when you call a function by itself such as f()
there is no execution context being set so JavaScript defaults it to the window
object (in the browser).
How do we make sure to get the required behavior in such cases ?
To make this have a desired value, we need modify the inner function’s context with indirect invocation using call()
or apply()
or create a bound function using bind()
or use the fat arrow syntax
introduced in ES6.
- Using
bind()
:
Here, bind(this)
will bind the execution context to this
which is obj
itself, meaning the function inner
bound to the obj
and will be called in the context of obj
.
NOTE :
Using bind()
will create a permanent context link, meaning once a function is bound to a give context using bind()
it cannot be re-bound or calling indrectly using the methods call()
or apply()
, doing that won’t show any effect.
Learn more about bind()
2. Using call()
:
Here, call(this)
will call the function inner()
in the context of this
which is passed in the arguments, thereby giving us the desired behavior.
Learn more about call()
call()
and apply()
are fairly similar, apply()
takes arguments for the calling function in the form of an array. Learn more about apply().
3. Using fat arrow syntax:
We can make use of the fact that arrow functions which don’t provide their own this
binding (it retains the this
value of the enclosing lexical context).
We can see how, the arrow function usesthis
from the enclosing scope, which is perfect when using in callbacks or looping when trying to maintain the outer context.
Great! You made it to the end of this blog! Hope this blog helped you get a clear idea of how this
in JavaScript works! 🎉
And, let me know in the comments if you find anything incorrect or if there is anything you’d like to add! Cheers! 🍻