Demystifying the "this" Keyword in JavaScript: A Beginner's Guide
Tags: webdev, beginners, javascript, programming
Published: 2023-05-27 06:03:34

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)
```
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
```
- **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
```
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!

```
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
```
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"

```

- **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
});
```


- **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!

```
**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
```


## 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](https://stackoverflow.com/questions/39716627/what-is-the-difference-between-explicitly-and-implicitly-in-programming-lang)(created by you the programmer) set the value of `this `for 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!