This is the 7th post in The Complete JavaScript Series.
Intro
Simply put, this
is a special variable that is created for every Execution Context.
Once this
has been created for the Execution Context (EC), it becomes a “keyword”. Then, it points to (or takes the value of) the parent of whatever function has used this
. The interesting thing about this
is that it behaves differently with respect to how it is used and called in different use cases. Let us see them one by one.
Different scenarios of ’this’ -
#1: Default Binding
A simple program that has nothing but this statement - console.log(this)
- will show that this
will point to the global window object, like so -
#2: Implicit Binding
’this’ in a method
A method is any function that is defined inside an object.
In the example below, this
will point to the parent object of the method that calls this
. Since getCurrentYear
is the method that calls this
, the value of this
will now point to the parent object - details
. Hence, this.futureYear
is equal to typing details.futureYear
.
const details = {
name: 'Vinoo',
futureYear: 2049,
getCurrentYear: function () {
console.log(2199 - this.futureYear)
console.log(this)
}
}
details.getCurrentYear() // 150
As we can see, we get the result 150
when the function is called. The value for futureYear
was accessed through the this
variable. The value of this
itself is the details
object -
’this’ in a function call
In a regular function call with strict mode enabled, this
will return undefined
👇
Otherwise, this
will point to the global window
object 👇
’this’ in Arrow Functions
In arrow functions, this
simply points to the this
of its surrounding function - which means this
points to the lexical scope/parent scope. This goes to say that arrow functions do not get their own this
.
Example -
#3: Explicit Binding
As the name suggests, explicit binding is a way to explicitly bind the value of this
to a specific object. There are 3 ways to do this -
-
call()
- Let’s say that our function is outside the object, and we still wantthis
in the function to point to the object. We can do that as follows -Here, we are “binding” the object
details
to the functiondisplayName()
so that thethis
variable in that function can point to the desired object. If we DO NOT use the “call” binding, then as usual,this
will simply point to the global window object.Now, what if we have multiple arguments to be passed? Look at the example below -
call()
successfully binds the details we have passed to theperson
object and then the elements of thehobbies
array, individually. But this is not the most efficient to bind things, is it? This is where theapply()
method helps us. -
apply()
- this method works exactly likecall()
except that we can pass the array variable itself as a parameter instead of the array elements individually. Everything else stays the same - -
bind()
- this method too, is almost no different from thecall()
orapply()
methods but there is an important advantage to using it. First, let’s look at an example -Notice how we assigned the
bind()
method to a variablefoo
and then called it as a function? This is becausebind()
returns a new function that we can then invoke anywhere we wish. Now for the advantage bit -foo
does not even get instantiated anywhere, does not have a reference, nothing. Even though theperson
object does not have a property namedfoo
, we can still explicitly bindfoo
toperson
much later in the program such thatperson
will now recognisefoo
as its own method.
#4: ’new’ Binding
new
is yet another special keyword that is exclusively used in the case of constructor functions. These are used to create new objects. Let’s look at this example -
let Wizard = function(name, spell) {
this.name = name
this.spell = spell
this.castMagic = function() {
console.log(this.name + ' has cast this spell - ' + this.spell)
}
}
let hermione = new Wizard('Hermione', 'Occulus Reparo')
let ron = new Wizard('Ron', 'Sunshine Daisies')
new
is used to denote that we are creating a new object (instantiating) for the Wizard
function. Note that Wizard
is capitalised when we use new
- a simple convention to differentiate, and also specify that this
variable will always point to the empty object created by new
. This is how we can get new instances easily for the same function with different arguments. Just simple Object Oriented Programming in action 😎
We will study more about constructors and classes in depth in a later post.
#5: HTML Event Element Binding - ’this’ in Event Listeners
In case of event listeners, this
points to the DOM element that the handler is attached to. Example -
sendBtn.addEventListener('click', function () {
console.log(2 + 3)
console.log('Value of this - ', this)
})
Here, on clicking the button ‘Send’, the value of this
will indeed be the DOM element button
that the function/handler is attached to.
NOTE - if this function/handler is an arrow function, then the value of this
again defaults to the global window object, like so -
sendBtn.addEventListener('click', () => {
console.log(2 + 3)
console.log('Value of this - ', this)
})
Closing Notes
That was it for this
!
We will study more about how this
is important for classes, constructors, and object oriented programming in the later posts.
Until the next one!
Keep shipping 🚀