Function & this
Functions are the building blocks of JavaScript, it is one of the programming languages that uses functional programming at the core. As easy as it is to use the functions, understanding this keyword is that complex. Because the value of this is decided at the execution time, unlike other programming languages.
As a Normal Function
The value of this in the function invocation refers to the global object. window in the browser and global in Nodejs.
function normalFunction() {
console.log(this === window);
this.name = "Arjunan";
}
normalFunction(); // true
console.log(window.name) // Arjunan
Strict mode
If you invoke the function with the strict mode the value of this will be undefined. It also affects all the inner functions that are defined in the function which is declared in strict mode.
function strictModeExample() {
"use strict";
console.log(this === undefined);
function inner() {
console.log(this === undefined);
}
inner();
}
strictModeExample();
this inside Method
When a function is declared inside an object the value of this inside that function will refer to the object it is declared in.
If the object is passed as a reference, then the context is shared between both the variables, the original and the one that has the reference.
const example = {
name: "Arjunan",
showName: function () {
console.log(this === example);
console.log(this.name);
},
};
example.showName();
// true
// Arjunan
example.name = "John Cena";
example.showName();
// true
// John Cena
const example2 = example
example2.name = "Rock"
example2.showName()
// true
// Rock
example.showName()
// true
// Rock
But, if we extract the method and save it in a variable, and then invoke the variable, the outcome will change. This is because when extracted to a variable and invoked it will be treated as a normal function.
const example = {
name: "Arjunan",
showName: function () {
console.log(this === example);
console.log(this === window);
console.log(this.name);
},
};
const show = example.showName;
show();
// false
// true
// undefined
If there are any inner functions inside the methods, the value of this inside them depends upon how the inner function is invoked.
Because the inner function is invoked as a normal function the value of this is a window object.
const example = {
name: "Arjunan",
showName: function () {
function inner() {
console.log(this === window);
console.log(this.name);
}
inner();
},
};
example.showName()
// true
// undefined
The fat arrow function does not have this of its own, it accesses this in its nearest scope.
const example = {
name: "Arjunan",
showName: function () {
const inner = () => {
console.log(this === example);
console.log(this.name);
};
inner();
},
};
example.showName();
// true
// Arjunan
this when invoked as constructor
The value of this in the function invoked as a constructor refers to a new object which has the value passed as an argument. Each instance creates a new object.
function Example(blog) {
this.blog = blog;
this.displayBlog = function () {
console.log(this.blog);
};
}
const example = new Example("Apple");
example.displayBlog();
// Apple
const example2 = new Example("Orange");
example2.displayBlog();
// Orange
console.log(example === example2);
// false
There are some methods in JavaScript that when invoked normally behave as a constructor.
let reg1 = RegExp(/[a-z]/i);
let reg2 = RegExp(/[a-z]/i);
console.log(reg1 === reg2);
// false
To avoid this we can add a check to the function which we want to be invoked as a constructor only.
function Example(name) {
if (!(this instanceof Example)) {
throw Error("Need to invoke as a constructor");
}
this.name = name;
}
const example1 = new Example("John");
console.log(example1.name);
// John
const example2 = Example("Rock");
// Error: Need to invoke as a constructor