DEV Community

Cover image for Demystifying the "this" Keyword in JavaScript: A Beginner's Guide
Danities Ichaba
Danities Ichaba

Posted on

Demystifying the "this" Keyword in JavaScript: A Beginner's Guide

Understanding the behavior of the this keyword is fundamental for writing effective and powerful JavaScript code. In this article, we would explore the concept of this in a simplified manner, demystifying(make it clearer and easier to understand.) its usage and providing code samples to clarify its behavior in different scenarios. By the end, you would have a solid foundation in using this to harness the full potential of JavaScript.

The behavior of this in JavaScript differs somewhat from other programming languages. Its value is determined by the context in which it is utilized, which can be perplexing(confuse) for beginners. Therefore, it's crucial to understand the context and to what this refers in various scenarios.

  • The Global Context Within the global execution context (that is, outside of any function), this refers to the global object in both strict mode and non-strict mode.

In a web browser, the global object is window, so this would refer to the window object:

console.log(this); // Output: Window (in a web browser)
Enter fullscreen mode Exit fullscreen mode

In a Node.js environment, the global object is not window but global. Hence, if you run the same piece of code in a Node.js context, this will refer to the global object:

console.log(this); // Logs "[object global]" in a Node.js context
Enter fullscreen mode Exit fullscreen mode
  • Function Context: Within a regular function, the value of this depends on how the function is invoked. If a function is called in the global context, this will be undefined in strict mode, or it will reference the global object in non-strict mode.
function func() {
  console.log(this);
}

func(); // Logs "[object Window]" in browser context in non-strict mode, or "undefined" in strict mode
Enter fullscreen mode Exit fullscreen mode

However, when the function acts as a method of an object, this refers to the object on which the method was invoked. This showcases that the value of this is not bound to the function itself but rather how and where the function is called, a concept known as execution context:

const person = {
  name: "John",
  greet() {
    console.log(`Hello, my name is ${this.name}!`);
  }
};

person.greet(); // Output: Hello, my name is John!

Enter fullscreen mode Exit fullscreen mode

However, arrow functions do not have their own this. Instead, they inherit this from the parent scope at the time of their creation. In other words, the value of this inside an arrow function is determined not by where or how it is called, but by the surrounding lexical context:

let obj = {
  prop: "Hello",
  func: () => {
    console.log(this.prop);
  }
}

obj.func(); // Logs "undefined" because `this` in the arrow function is not bound to `obj` but to its parent scope
Enter fullscreen mode Exit fullscreen mode

This can be advantageous in some scenarios, but it also makes arrow functions unsuitable for methods that need to access other properties of the object on which they are invoked.

  • Constructor Function: When a function is used as a constructor to create new n a constructor function, this refers to the newly created object. But, what does 'newly created' mean here? To understand this, we need to explore the new keyword in JavaScript. When you use new before a function call, it tells JavaScript to do four things:
  1. Create a new, empty object. This is not a function, an
    array, or null, it's just an empty object.

  2. Make this in the function refer to that new object.
    The new object gets linked to the this keyword within
    the constructor function. This is why this.name inside
    Person(name) is actually modifying the new object.

  3. Execute the function normally. It runs through the
    function code as it would normally do.

  4. If the function doesn't return its own object, return
    the new object. If the constructor function returns an
    object, that object will be returned instead of the new
    object. If it returns anything else, the new object is
    returned.
    The new keyword allows JavaScript developers to use the language in an object-oriented style, creating instances from constructor functions much like classes in other languages. This also means the this keyword inside constructor functions behave as you might expect if you're coming from a class-based language, referring to the new instance of the object.

function Person(name) {
  // `this` is a new, empty object when the function is invoked with `new`
  this.name = name; // `this` now has a property `name`
  // The function ends, and `this` is returned because there's no other object being returned by the function
}

let john = new Person('John'); // `john` is now the object returned by the function `Person`, which includes a property `name` with a value of 'John'
console.log(john.name); // Logs "John"

Enter fullscreen mode Exit fullscreen mode
  • Event Handlers: In the context of an event handler, this refers to the element to which the event listener is attached to - the same as the same as event.currentTarget.
const button = document.querySelector("button");

button.addEventListener("click", function() {
  console.log(this); // Output: <button> element
});
Enter fullscreen mode Exit fullscreen mode
  • Explicit / Implicit Binding: JavaScript provides methods like call() and apply() to explicitly specify the value of this when invoking a function. Here's an example:
function sayHello() {
  console.log(`Hello, ${this.name}!`);
}

const person = {
  name: "John"
};

sayHello.call(person); // Output: Hello, John!

Enter fullscreen mode Exit fullscreen mode

Bind Method and Permanent this Context
JavaScript provides a built-in method called bind that allows us to set the this value in methods. This method creates a new function, when invoked, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

The uniqueness of the bind method is that it creates a new function with a permanently bound this value, regardless of how the function is later called. In other words, once you have used bind to set the this value in a function, it cannot be changed — not even with call or apply. The example below demonstrates how bind provides a way to lock the this value in a function, which can be helpful in various scenarios. For example, when you're setting up event handlers and you want the this value to always refer to a specific object, or when you're working with a library or framework that calls your callback function and you want to control what this refers to inside that callback.

function greet() {
  return `Hello, I am ${this.name}`;
}

let person1 = { name: 'Bose' };
let person2 = { name: 'Ali' };

// Create a bound function with "this" set to person1
let greetPerson1 = greet.bind(person1);

console.log(greetPerson1()); // Hello, I am Alice

// Attempt to change the context by using the call method; however, it still uses person1 as 'this' context
console.log(greetPerson1.call(person2)); // Hello, I am Bose

//  In contrast, a normal function call allows the 'this' context to be set by the call method
console.log(greet.call(person2)); // Hello, I am Ali
Enter fullscreen mode Exit fullscreen mode

Conclusion:

A crucial concept to grasp in JavaScript is that the this value in a function object is usually not fixed -- it often varies based on the context in which the function is invoked. In other words, the this value within a function is typically determined at the time of its execution, rather than at the moment of its definition. However, there are exceptions to this rule. When using bind(), call(), or apply()methods on a function, these methods allow you to explicitly(created by you the programmer) set the value of thisfor the invocation of the function, thereby overriding its default behavior. Additionally, arrow functions in JavaScript behave differently. They do not bind their own this value. Instead, they capture the value of this from the outer lexical environment in which they are defined, and this value remains constant throughout the lifecycle of the function. These nuances make understanding and using this in JavaScript both challenging and important.

Understanding the "this" keyword unlocks the true potential of JavaScript. By grasping its behavior in different contexts, you can effectively access and manipulate properties and methods within objects, handle events, and create powerful constructor functions. Embrace the power of "this" in your JavaScript journey and take your coding skills to new heights!

Now that you have a solid foundation in the this keyword, go ahead and confidently write JavaScript code, leveraging its power to create dynamic and interactive applications.

Happy coding!

Top comments (6)

Collapse
 
nima_lalaj profile image
yasin cengiz

Simple, and helpful, I like it.

Collapse
 
danities316 profile image
Danities Ichaba

Thank you

Collapse
 
codecraftjs profile image
Code Craft-Fun with Javascript

Good Explanation ! Meticulous Content.

Collapse
 
danities316 profile image
Danities Ichaba

Thanks boss

Collapse
 
danities316 profile image
Danities Ichaba

Thank you brotherly

Collapse
 
loboweissmann profile image
Henrique Lobo Weissmann (Kico)

Great post, thank you!