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: "john@email.com",
printInfo: function () {
console.log(`${this.id} - ${this.name} - ${this.email}`);
}
};
student.printInfo();
// 123 - John Doe - john@email.com
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
thisRecall 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:
bindbind 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
callImagine 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
callsfunction 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.
thisthis 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.