Problem: Why is this Undefined in a JavaScript Function?

Question:

I am trying to access an object’s property using this inside a function, but it returns undefined. Here is my code:

const user = {
name: 'John',
greet: function() {
console.log('Hello, ' + this.name);
}
};

setTimeout(user.greet, 1000);

I expect the output to be Hello, John, but it logs Hello, undefined. Why is this.name undefined, and how can I fix it?

 

Solution: Understanding this and How to Bind It Correctly:

This issue arises because of how the value of this is determined in JavaScript. In your code, when the greet function is passed as an argument to setTimeout, it loses its original context.

Explanation:

In JavaScript, the value of this inside a function depends on how the function is called. When you use setTimeout(user.greet, 1000);, the function is called without any context, so this inside greet defaults to the global object (window in browsers), or undefined in strict mode.

That’s why this.name is undefined—it’s looking for name on the global object instead of the user object.

Solutions:

  1. Use bind() to explicitly set this:You can use bind() to ensure the greet function always uses the correct context:
    setTimeout(user.greet.bind(user), 1000);

    Here, bind(user) returns a new function where this is always bound to user.

  2. Use an Arrow Function:Arrow functions don’t have their own this context; they inherit it from the surrounding scope:
    setTimeout(() => user.greet(), 1000);

    This works because the arrow function captures the correct context (user) when it is defined.

  3. Store this in a Variable:Another common workaround is to store the correct this context in a variable:
    const user = {
    name: 'John',
    greet: function() {
    const self = this;
    setTimeout(function() {
    console.log('Hello, ' + self.name);
    }, 1000);
    }
    };

    user.greet();

    In this case, self (or that) is used to hold the reference to the original this context.

    Final Code Example with bind():

    const user = {
    name: 'John',
    greet: function() {
    console.log('Hello, ' + this.name);
    }
    };

    setTimeout(user.greet.bind(user), 1000); // Output: Hello, John

Conclusion:
Understanding how this works in JavaScript is crucial, especially when passing functions as arguments or using them in callbacks. Using bind(), arrow functions, or storing the context can help you avoid issues like this becoming undefined.

Related Blog

Sign up for our newsletter to stay up to
date with tech news!