The Scope of “this” in Javascript
This is a blog about this
.
What’s this about?
This article is about the infamous this
in Javascript. We’ll see it’s different behaviours in different situations it used in. So let’s jump into this. (Pun Intended)
Setup
As I want you guys to learn by doing I suggest you to press cmd+option+j
(for mac) or ctrl+shift+j
and follow along with the code examples sown below in the github gists.
The story of ‘this’
If you are any other object-oriented language ‘this’ must be a very clear and easy concept for you. But in the world of javascript in order to make difficult things easy, we made easy things hard in some cases.
A function’s
this
keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
Some reasons why it is so…
Javascript is a scripting language which means that there is no compilation step in code execution. The interpreter reads the code and executes it line by line. The environment (or scope) in which the line is being executed is known as “Execution Context”. The Javascript runtime maintains a stack of these execution contexts and the execution context present at the top of this stack is currently being executed. The object that “this” refers changes every time execution context is changed.
The different behaviours of ’this'
Default Behaviour
The execution context for execution is global by default. So if a code is executed in a simple function call then this
refers to the global object (in case of nodejs) or window object (in case of browser).
1function that () {2 console.log("Normal call");3 console.log(this === window);4}5that();6console.log(this === window)
If you execute the above gist in the browser console you’ll see true
to be printed both times.
BEWARE
If strict mode is enabled for any function then the value of “this” will be “undefined” as in strict mode, global object refers to undefined in place of windows object.
Try copy pasting this in the console and see the difference.
1"use strict";2function that () {3 console.log("Normal call");4 console.log(this === window);5}6that();
IIFE
In IIFE (Immediately Invoked Function Expression) this performs in a similar fashion to a normal function shown above also abiding the fact that in strict mode value of “this” will be undefined inside the function.
Object-Oriented Programming
The ‘new’ Instance
When an object is created in Javascript using the new
keyword then the function invoked is known as the constructor function. And the value of this depends refers to the newly created object.
1function Those(init) {2 this.is_a_preposition = init;34 this.displayProperty = function() {5 console.log(`Is those a preposition? : ${this.is_a_preposition}`);6 }7}89let word = new Those("yes");10word.displayProperty(); //Prints :- Is those a preposition? : yes1112let word2 = new Those("no");13word2.displayProperty(); //Prints :- Is those a preposition? : no
In the case of word.displayProperty(), “this” refers to new instance word and in case of word2.displayProperty(), “this” refers to word2 which is a different instance of Those.
BEWARE of the execution context…
Look at the example below
1function those () {2 'use strict';3 console.log("Strict function hence this is undefined,Or is it?")4 console.log(this === window);5}67let confused = {8 those: those,9 these: function() {10 console.log(this === window);11 }12}13confused.those(); //FALSE14let evenMoreConfused = confused.these;15evenMoreConfused(); //TRUE16confused.these(); //FALSE
What is happening here?
- confused.those() — It prints
**false**
as now the this is not thewindow
object, it is theconfused
object. - evenMoreConfused() — It prints
**true**
as it is invoked as a normal function andthis
is now thewindow
object. - confused.these() — Even though it is the same as evenMoreConfused() but it is invoked by the confused object so
this
refers toconfused
object. So it prints**false**
.
Arrow Functions
In an arrow function, a very interesting thing happens. When a fat arrow is used then it doesn’t create a new value for **this**
. **this**
keeps on referring to the same object it is referring, outside the function.
1let confused = {2 those: function() {3 console.log(this === window);4 },5 these: ()=> {6 console.log(this === window);7 }8}910confused.those(); //False11confused.these(); //True
In the above example, you can see **these**
and **those**
differ only in function declaration but the scope for **this**
changes.
Bind Method
Bind method changes the existing method and returns a new one in a way that this
inside it now refers to the parameter provided to the bind function. See the example below.
1function Preposition(name_init) {2 this.name = name_init;34 this.displayName = function() {5 console.log(`Preposition is ${this.name}`);6 }7}89let these = new Preposition("these");10these.displayName(); // Prints Preposition is these11let those = new Preposition("those");12those.displayName(); // Prints Preposition is those1314let thoseDisplay = these.displayName.bind(those); // Creates new function with value of “this” equals to "those" object15thoseDisplay(); // Prints:- Preposition is those
So we just changed the execution context of **these.displayName**
by the bind method.
Call, Apply Method
Call and Apply work the same way as Bind method. The only difference being they don’t return a new function but execute the existing one with the execution context provided in the parameters.
Call, Apply, Bind these methods can be used to set a custom value of “this” to the execution context of the function.
I’ll try to explain the above statement by the example below.
1function Preposition(name_init) {2 this.name = name_init;34 this.displayName = function() {5 console.log(`Preposition is ${this.name}`);6 }7}89let these = new Preposition("these");10these.displayName(); // Prints Preposition is these11let those = new Preposition("those");12those.displayName(); // Prints Preposition is those1314these.displayName.call(those); // // Prints:- Preposition is those
Summing Up
So I’ve tried my best to demystify the infamous this
keyword in Javascript. I hope you guys liked my efforts to explain this concept as concisely as possible. Open for both criticism and compliments :)