this
keyword
this
keywordthis
keyword is set in different contextsthis
keyword is mostly used inside functions to refer to the object using which the function was invoked.this
keyword becomes applicable for referencing the object used to invoke the function.this
keyword is like an implicit parameter passed to a functionthis
is set when the function is invoked.this
inside a function depends on how that function is called.const student = {
id: 123,
name: "John Doe",
email: "[email protected]",
printInfo: function () {
console.log(`${this.id} - ${this.name} - ${this.email}`);
}
};
student.printInfo();
// 123 - John Doe - [email protected]
function orderFood() {
console.log("Order confirmed against the name: " + this.fullName);
}
orderFood();
// non-strict mode:
// Order confirmed against the name: undefined
// strict-mode:
// Uncaught TypeError: this is undefined
global
object, which in the case of browsers is the window
objectIn the global scope, the value of this
depends on the environment in which our JavaScript code is executed.
In the case of browsers, the value of this
in the global scope is the window object.
In NodeJS, the value of this
depends on whether we are using the ECMAScript modules or the CommonJS modules.
In ECMAScript modules, the value of this
is undefined at the top level of a module. This is because the code in ECMAScript modules is executed in strict mode.
In CommonJS modules, at the top level of a module, this
refers to the module.exports object.
In Node.js, the JavaScript code is technically not executed in a global scope. Instead, it is executed in a module scope, where commonly used modules are CommonJS and ECMAScript modules
Inside web workers, the value of this
at the top level refers to the global scope of the web worker, which is different from the global scope containing the window object in the browser.
When a function is invoked as a constructor function using the new
keyword, the this
keyword inside the constructor function refers to the newly created object.
The new keyword creates a new object and sets the newly created object as the value of this
.
As a result, we can use this
inside a constructor function to add properties to the newly created object.
function Recipe(name, ingredients) {
this.name = name;
this.ingredients = ingredients;
}
name
and ingredients
to the newly created object.Code inside a class in JavaScript is executed in strict mode.
the value of this
inside methods is either undefined
if not invoked on an object or the class instance itself, which is used to invoke the method.
class Shape {
constructor(color) {
this.color = color;
}
printColor() {
console.log(this.color);
}
}
const circle = new Shape("Red");
const printColorFn = circle.printColor;
printColorFn();
// Error: this is undefined
this
Recall how the value of this gets set inside a function. It depends on how the function is called.
the value of this depends on whether our code is in strict mode or not
function Counter(startingValue) {
this.value = startingValue;
}
Counter.prototype.incrementFactory = function (incrementStep) {
return function () {
this.value += incrementStep;
console.log(this.value);
};
};
const counter = new Counter(0);
const increment5 = counter.incrementFactory(5);
increment5(); // NaN
increment5(); // NaN
increment5(); // NaN
Assuming that our code is in non-strict mode, the value of this inside the increment5
function is the global object, i.e., the window
object in the case of browsers
this.value
is actually window.value
, and it is undefined
because the window
object, by default, doesn’t have a value
property.
As a result, we get the NaN
value when undefined
is added to a number, i.e., the value of the incrementStep
parameter
this
...
Counter.prototype.incrementFactory = function (incrementStep) {
const thisVal = this; // save `this` value
return function () {
thisVal.value += incrementStep;
console.log(thisVal.value);
};
};
...
increment5(); // 5
increment5(); // 10
increment5(); // 15
...
Counter.prototype.incrementFactory = function (incrementStep) {
return () => {
this.value += incrementStep;
console.log(this.value);
};
};
...
increment5(); // 5
increment5(); // 10
increment5(); // 15
Using an arrow function solves the problem because, unlike regular functions, which get their own value of this when they are invoked, arrow functions don’t get their own this value
the value of this inside an arrow function is taken from the surrounding context.
in the DOM context where this
refers to the element that triggered the listener…
const btn = document.querySelector("button");
class FormHandler {
constructor(submitBtn) {
submitBtn.addEventListener("click", this.submitForm);
}
submitForm() {
this.sendRequest();
// ERROR: this.sendRequest is not a function
}
sendRequest() {
console.log('sending request...');
}
}
new FormHandler(btn);
this.sendRequest()
call throws an error because this
needs to refer to an instance of the FormHandler
class to allow us to call other methods in this class from within the submitForm
method.
So the problem is, how can we call the sendRequest
method from the submitForm
method?
there is more than one way to solve this problem.
One of them is to use an arrow function.
...
submitBtn.addEventListener("click", () => this.submitForm());
...
Javascript also provides us with ways to explicitly set this to whatever value we want.
We can use any of the following three built-in methods to explicitly set the value of this
:
bind
bind
to access this
function Counter(startingValue) {
this.value = startingValue;
}
Counter.prototype.incrementFactory = function (incrementStep) {
// return function () {
const incrementFn = function () {
this.value += incrementStep;
console.log(this.value);
};
// return a function with `this` bound
// to the object used to invoke the
// `incrementFactory` method
return incrementFn.bind(this);
};
const counter = new Counter(0);
const increment5 = counter.incrementFactory(5);
increment5(); // 5
increment5(); // 10
increment5(); // 15
call
Imagine having an object that contains methods that can be useful for other objects as well.
can we use those methods with other objects? without duplication.
const john = {
name: "John",
sayHello() {
console.log("Hello, I am " + this.name);
}
};
const sarah = {
name: "Sarah"
};
// borrow a method from john
const sayHello = john.sayHello;
sayHello.call(sarah);
// Hello, I am Sarah
call
sfunction Employee(name, age, id) {
this.name = name;
this.age = age;
this.id = id;
}
function BankEmployee(name, age, id, bankName) {
// delegate the responsibility of adding
// "name", "age", and "id" properties to
// the Person constructor
Employee.call(this, name, age, id);
this.bankName = bankName;
}
call
method has been used to call the Employee
constructor, passing in the three properties that the Employee
constructor can set on the newly created object.
this
inside the BankEmployee
function will be the newly created object.
In other words, the Employee
constructor is invoked from inside of the BankEmployee
constructor, with this
explicitly set to the newly created BankEmployee
object.
this
problemconst btn = document.querySelector("button");
class FormHandler {
constructor(submitBtn) {
submitBtn.addEventListener("click", this.submitForm);
}
submitForm() {
this.sendRequest();
// ERROR: this.sendRequest is not a function
}
sendRequest() {
console.log('sending request...');
}
}
new FormHandler(btn);
this
inside the submitForm
method.submitBtn.addEventListener("click", this.submitForm.bind(this));
globalThis
is a globally available property in JavaScript that allows us to access the global object regardless of which environment our JavaScript code is executed in.
this
this
has in different contexts:arrow function
, the value of this is taken from the surrounding context
.regular function
, the value of this depends on how a function is called
and whether the code is executed in strict mode
or not.
constructor
using the new
keyword, the value of this
is the newly created object.this
is explicitly set using bind
, call
, or apply
functions, then the value of this is whatever value is passed as the first argument to these functions.function
is invoked as a “method”, the value of this
is the object used to call the method.function
is invoked without any object, i.e., as a “function”, the value of this is the global object in non-strict mode and undefined
in strict mode.this
refers to the global window
object.