In JavaScript, the this
keyword provides a reference to the current execution context. However, when functions are nested, determining the correct this
context can be challenging. Let’s explore this concept with a detailed example.
Nested Functions and this
Context
Consider a scenario where a function is called within another function:
function outerFunction() {
innerFunction();
}
In this example, innerFunction
doesn't have a clear reference to this
within outerFunction
. Here's a visualization of the call stack:
and below callMe(), we have an execution context of the parent function.
In such cases, this
typically refers to the Global Execution Context (GEC). In a browser environment, this means the window
object, while in a Node.js environment, it refers to an empty object.
Example: Setting User Details
Let's see how this works in practice:
function setUsername(username) {
this.username = username;
console.log("called");
}
function createUser(username, email, password) {
setUsername(username);
this.email = email;
this.password = password;
}
const chai = new createUser("chai", "chai@fb.com", "123");
console.log(chai);
//outputs: createUser { email: 'chai@fb.com', password: '123' }
Notice that the username
property is missing. This occurs because setUsername
is called without a proper this
context, causing it to refer to the GEC.
Also, the function is getting called, but after the function has done its work, it gets out of the call stack and the memory is released, Also we have given a reference to the function, now you will think that "setUsername(username)" is a function call in itself, but it's only the reference.
Therefore, in JS we get some methods through which we can explicitly call the functions, and one of those methods is "call".
Now if we only use "call", then output will be the same as earlier, as after the function has done its work, it gets out of the call stack and memory is released, therefore we don't get that variable inside the parent function.
Therefore we have to hold the reference and for this purpose, we can use "call" for explicitly calling and holding the reference.
Now, we also have to pass execution context, as we are saying to the child function that don't use your "this" as it is going to be released.
But use my "this" i.e of parent function, therefore we have written it like "setUsername.call(this, username)"
Explicitly Setting this
with call
To resolve this issue, we can use the call
method to explicitly set the this
context of setUsername
:
function setUsername(username) {
this.username = username;
console.log("called");
}
function createUser(username, email, password) {
setUsername.call(this, username);
this.email = email;
this.password = password;
}
const chai = new createUser("chai", "chai@fb.com", "123");
console.log(chai);
//outputs:
called
createUser { username: 'chai', email: 'chai@fb.com', password: '123' }
By using "setUsername(this, username)", we ensure that setUsername
uses the this
context of createUser
.
Significance of "new" keyword:
Object Creation: The
new
keyword creates a new empty object.Prototype Linking: The new object's prototype is set to
createUser.prototype
.Context (
this
): Thethis
context insidecreateUser
is bound to the new object.SetUsername Call:
SetUsername.call
(this, username)
sets theusername
property on the new object.Property Setting:
this.email
andthis.password
are set on the new object.Implicit Return: If no object is explicitly returned, the newly created object is returned.
Assignment: Therefore,
chai
is assigned the new object with the propertiesusername
,email
, andpassword
.
Key Points to Remember
Global Execution Context (GEC): In a browser,
this
refers to thewindow
object. In Node.js, it refers to an empty object.Function Calls: When a function is called inside another function,
this
may not refer to the intended context.Using
call
: Thecall
method can explicitly setthis
for a function, ensuring it uses the correct context.
Understanding and using call
effectively allows us to manage this
context accurately, ensuring our functions behave as expected.