Demystifying the 'this' Keyword in JavaScript
Preface:
Before understanding 'this' let's understand a problem statement, where we have two objects of the same kind and each object has a variable and a method; and the method is trying to refer the variable within it.
const user1 = {
name: "Alex",
introduce: function() {
console.log("Hi, I am " + user1.name);
}
};
user1.introduce();
const user2 = {
name: "Marty",
introduce: user1.introduce
};
user2.introduce();
"Hi, I am Alex"
"Hi, I am Alex"
In the above example, if user2 wants to use the functionality of 'introduce' from user1, we won't be able to do that cause the method in user1 will always refer to the 'name' of user1.
To resolve this, user2 either has to completely replicate the method by re-writing it, else user1 and user2 will share a method, where the variables they want to refer to needs o tbe passed in the method params.
// Solution 1
const user2 = {
name: "Marty",
introduce: function() {
console.log("Hi, I am " + user2.name);
}
};
// Solution 2
const introduceUser = function(name) {
console.log("Hi, I am " + name);
}
const user1 = {
name: "Alex",
introduce: introduceUser
};
user1.introduce();
const user2 = {
name: "Marty",
introduce: introduceUser
};
user2.introduce();
Both of which are not viable solutions to our problem.
Solution:
This is where the this keyword comes into picture. Imagine this just like a pronoun, which value changes depending on who called the function. In our case, if user1 calls this the function, this would refer to user1. Same goes with user2.
THIS Keyword
this is an implicit reference to the object that is currently executing the piece of JavaScript code.
When this is used within functions, it's value is not determined by where a functions is written; rather it's determined by how the function is called (ie. to determine this, we simply need to find the 'caller')
this Inside Objects (The Method Context)
The most common place 'this' is used is inside an object's method. We can use to implicitly refer to the same object from within it instead of using the object's variables in a hardcoded manner.const user1 = { name: "Alex", introduce: function() { console.log("Hi, I am " + this.name); } }; user1.introduce(); const user2 = { name: "Marty", introduce: user1.introduce }; user2.introduce();"Hi, I am Alex" "Hi, I am Marty"Because 'this' depends entirely on how a function is called, we can take the exact same function, call it in a different way, and completely change the value of 'this'.
this Out in the Open (The Global Context)
Whenever we are at the top-level of the code, outside any function, object or class, the 'this' keyword points to the Global Object. However the exact identity of the Global Object changes depending on the JS enviroment, i.e.In the Browser (window)
When JavaScript runs in a standard web browser, the global object is the window object, which represents the browser tab that our script is currentyl running on.In Node.js (global)
Node.js runs JavaScript on a server or your computer's backend, not in a browser. Therefore, there is no "window" to point to. Instead, Node.js has a global object simply called global.In Web Workers (self)
Web Workers allow you to run JavaScript in the background of a browser so you don't freeze the main user interface. However, for security and performance, Web Workers are not allowed to touch the DOM, which means they do not have access to the window object. Inside a Web Worker, the global object is called self.Modern Solution (globalThis)
Finding the global object is messy, cause it changes based on the environment. So instead globalThis was introduced that will always point to the environment's global object, regardless of where the code is running.// The old way of finding the global object var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); }; let globalObj = getGlobal(); // The modern way let globalObj = globalThis;
this Inside Regular Functions
Inside regular functions, this refers to the global object is globalThis.function sayHello() { this.name = "Sam"; console.log(this); } sayHello(); console.log(globalThis.name);The thing to notice here is; Currently it looks like from inside the function, it's unable to find this, hence it's searching it globally and using the globalThis. But in reality, it's working as if the caller has passed an hidden 'this' object as a parameter to the function. (PS. This observation will be useful while learning call(), apply(), bind()).
Note: In strict mode in JavaScript (ie. using "use strict"; directive), this inside functions will result in undefined as JavaScript will turn off this fallback of passing globalThis to the function.
