Understanding ‘this’ in JavaScript – A Personal Journey from Confusion to Clarity

Table of Contents

Understanding ‘this’ in JavaScript – A Personal Journey from Confusion to Clarity

Introduction

When I started my journey as a JavaScript developer, one of the most confusing concepts I struggled with was the use of the ‘this’ keyword. It came across to change its behavior depending on where and how it was used, sometimes pointing to an object, to undefined, and other times to the window object. I kept getting errors and unexpected results. At one point, I considered avoiding it altogether.

Understanding ‘this’ is an important concept in JavaScript and is foundational for mastering the language.

But as I dove deeper into frameworks like React, I realized I could not escape ‘this.’ I had to learn it, and once I did, it became one of the most powerful tools in my developer’s toolbox. So, whether you are just starting or brushing up, let me walk you through everything I have learned about ‘this’ in a way I wish someone had explained to me before.

What is ‘this’ in JavaScript

In simple terms, ‘this’ is a reference to an object that is available in the block or lexical scope of a function. The value of ‘this’ is determined by the function context and the way the function is invoked.

Think of this as a context pointer; it points to who is calling the function. Its value depends on how a function is called, not where it is written. Understanding the function definition and the current execution context is key to predicting what ‘this’ will refer to.

Why is ‘this’ Important

Knowing how ‘this’ works allows you to:

  • Access object properties inside methods.
  • Write more reusable and maintainable code.
  • Understand and use classes, event handlers, and framework-specific code (like React, Vue).
  • Avoid common bugs and improve debugging.

Use Cases of ‘this’ in JavaScript

1. Global Scope

// JavaScript
console.log(this) // In browser: Window, In Node: {}

Global scope of ‘this’ refers to the global window object that consists of browser window properties and functions.

2. In a Regular Function

// JavaScriptfunction show() {
console.log(this);
}show();

When you call show()directly (not as a method of an object), the value of ‘this’ depends on whether you are in strict or non-strict mode.

In non-strict mode, ‘this’ refers to a global object (window object for browsers).
In strict mode, ‘this’ is undefined, because the strict mode prevents ‘this’ from defaulting to the global object in standalone function calls.

// JavaScript
‘use strict’;function show() {
console.log(this); // undefined
}show();

3. In Event Listeners

// JavaScriptdocument.getElementById(‘myBtn’).addEventListener(‘click’, function(){
console.log(this); // Button element
});

In the above illustration, we are adding event listener on a button with id = myBtn. When an event triggers, the callback function is called. In this situation, ‘this’ refers to the element that receives the event, and the button element is returned.

Important difference with arrow functions

If you use an arrow function rather:

// JavaScriptdocument.getElementById(‘myBtn’).addEventListener(‘click’, () => {
console.log(this); // window object
});

Arrow functions do not have their own ‘this’. They take ‘this’ from the outer or lexical scope where arrow functions are defined. So, here, ‘this’ would generally be the window object (or whatever the lexical scope’s ‘this’ is).

4. Inside an Object Method

// JavaScriptconst user = {
name: ‘Rishi’,
greet() {
console.log(`Hi, I’m ${this.name}`);
}
};user.greet();

In this illustration, we have an object user with a property name and method greet. When you call user.greet(), JavaScript looks at how the function is called. Since you are calling it through the object (user.greet()), the keyword ‘this’ inside that function points to the object user.

The output is: Hi, I’m Rishi
If we take the function reference and call it separately

// JavaScriptconst user = {
name: ‘Rishi’,
greet() {
console.log(`Hi, I’m ${this.name}`);
}
};const greetFunc = user.greet;
greetFunc(); // Hi, I’m undefined, this refers to window object

Now ‘this’ does not point to the user anymore, so this.name becomes undefined because points to the window object.

5. Inside an Arrow Function

// JavaScriptconst user = {
name: ‘Rishi’,
greet: () => {
console.log(`Hi, I’m ${this.name}`); // undefined
}
};user.greet();

In this illustration, method greet is defined using the arrow function. As we know, the arrow function does not have its own ‘this,’ so ‘this’ refers to its lexical scope. In our case, the arrow function’s lexical scope is object literal. But object literal does not create its own ‘this’ binding. Hence, ‘this’ inside greet comes from the object’s lexical scope where the object is defined. In our case ‘this’ is the window object that does not have the name property.

The output is: Hi, I’m undefined

6. With Call, Apply, and Bind

// JavaScriptfunction greet() {
console.log(`Hello, ${this.name}`);
}const person = { name: “Rishi” };
greet.call(person); // Hello Rishi
greet.apply(person); // Hello Rishiconst greetRef = greet.bind(person);
greetRef(); // Hello Rishi

In this illustration, we are controlling ‘this’ explicitly using .call(), .apply(), and .bind() methods.

.call(thisArg, …args) calls the function immediately with the ‘this’ value you provide. In our example, ‘this’ is a person.

.apply(thisArg, [argsArray]) is nearly the same as .call(). The only difference is that .call() takes arguments as comma separated, whereas .apply() takes arguments as an array.

.bind(thisArg, …args) does not call the function immediately. Instead, it creates a new function where ‘this’ is permanently set to the value you give (person).

Use Cases of ‘this’ in JavaScript

React class components rely heavily on ‘this.’

❌ Problem Example

// JSXclass MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}increment() {
this.setState({ count: this.state.count + 1 });
}render() {
return ;
}
}

Without binding, this.increment loses the context of the class, leading to a runtime error.

✅ Bind increment function with class ‘this’ instance:

// JSXclass MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.increment = this.increment.bind(this);
}increment() {
this.setState({ count: this.state.count + 1 });
}render() {
return ;
}
}

Class methods do not bind ‘this’ by default. When you pass a method like increment as callback or event listener, the context of ‘this’ is not preserved, unless you explicitly bind it.

✅ Fix Using Arrow Function

// JSXclass MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}increment = () => {
this.setState({ count: this.state.count + 1 });
};render() {
return ;
}
}

As we know, arrow functions do not have their own ‘this,’ It refers ‘this’ to its lexical scope. In our case, arrow function’s lexical scope is MyComponent class.

Best Practices for Using ‘this’

Mastering the ‘this’ keyword in JavaScript is all about using it intentionally and consistently. Here are some best practices to help you avoid common pitfalls and write robust, efficient code:

  • Use this to access the properties and methods of the current object, especially within object methods and class instances.
  • When you need to explicitly set the value of this, use the bind() method to create a bound function with a specific context.
  • Leverage arrow functions to inherit this from the surrounding scope, which is especially useful in callbacks and nested functions.
  • Avoid relying on this in the global scope, as its value can be confusing and may lead to unexpected results, especially in strict mode.
  • Use console.log(this) to inspect the current value of this during development and debugging.
  • Enable strict mode in your code to prevent accidental binding of this to the global object and to catch errors early.
  • Use the new keyword to create new objects and ensure that this refers to the newly created instance.
  • Access the global object in a cross-platform way using globalThis, which works in both browsers and Node.js.
  • Maintain a consistent coding style and use tools like linters to catch mistakes in your use of this.
  • When defining functions, be clear about whether you want this to refer to the global object, a specific object, or to be inherited from the enclosing context.
  • Remember that using call(), apply(), or bind() allows you to control the context in which a function is executed.
  • Always be aware of the execution context and how it affects the value of this, especially when passing functions as callbacks or event handlers.

By following these best practices, you’ll be able to harness the full power of the ‘this’ keyword in JavaScript, avoid common errors, and write code that is both efficient and easy to understand.

❌ Cons:

  • You may introduce subtle bugs.
  • Event handlers in React may break.
  • Misuse can lead to memory leaks.

You will struggle with OOP (Object-Oriented Programming) and class inheritance.

✅ Pros:

  • Write cleaner, context-aware code.
  • Debug errors faster.
  • Use frameworks and advanced patterns confidently.

Conclusion

If you truly want to become a professional JavaScript developer, understanding ‘this’ is non-negotiable. It might feel frustrating at first (trust me, I have been there), but once it clicks, it unlocks a whole new level of clarity in writing and understanding code.

So do not ignore ‘this’ — embrace it, experiment with it, and it will make you a better JavaScript and React developer.

Know More: Embedded Software Development Services

Picture of Rishi Bhati

Rishi Bhati

Rishi Bhati is a Senior Software Engineer at eInfochips. specializing in MERN stack development and building scalable, high-performance web applications. He is passionate about continuous learning and adopting modern technologies such as GenAI, LLM, and RAG models.

Explore More

Talk to an Expert

Subscribe
to our Newsletter
Stay in the loop! Sign up for our newsletter & stay updated with the latest trends in technology and innovation.

Download Report

Download Sample Report

Download Brochure

Start a conversation today

Schedule a 30-minute consultation with our Automotive Solution Experts

Start a conversation today

Schedule a 30-minute consultation with our Battery Management Solutions Expert

Start a conversation today

Schedule a 30-minute consultation with our Industrial & Energy Solutions Experts

Start a conversation today

Schedule a 30-minute consultation with our Automotive Industry Experts

Start a conversation today

Schedule a 30-minute consultation with our experts

Please Fill Below Details and Get Sample Report

Reference Designs

Our Work

Innovate

Transform.

Scale

Partnerships

Quality Partnerships

Company

Products & IPs

Privacy Policy

Our website places cookies on your device to improve your experience and to improve our site. Read more about the cookies we use and how to disable them. Cookies and tracking technologies may be used for marketing purposes.

By clicking “Accept”, you are consenting to placement of cookies on your device and to our use of tracking technologies. Click “Read More” below for more information and instructions on how to disable cookies and tracking technologies. While acceptance of cookies and tracking technologies is voluntary, disabling them may result in the website not working properly, and certain advertisements may be less relevant to you.
We respect your privacy. Read our privacy policy.

Strictly Necessary Cookies

Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.