Interview Q&A / JavaScript

IntermediateIn-depth3 min readUpdated 2 Oct 2026

How does the this keyword work in JavaScript?

SHORT ANSWER

this is decided by how a function is called, not where it is written. A method call obj.fn() sets this to obj; new sets it to the new object; call, apply and bind set it explicitly; a plain call gives undefined in strict mode. Arrow functions have no own this and use the surrounding one.

Explain it simply

The word "this" in a sentence depends on who is speaking. If Rohit says "this bat is mine", it is Rohit's bat. If Virat says the same sentence, it is Virat's bat. The sentence is the same; the speaker changes the meaning.

In JavaScript, a normal function is the sentence, and this is the speaker. It is decided at the moment of the call, by looking at how the function was called. The same function can have a different this every time.

Arrow functions are the exception. They do not have their own this. They borrow this from the code around them, like repeating what the person next to you said.

Example

js
const user = {
  name: "Priya",
  greet() {
    return "Hi, " + this.name;
  },
};

console.log(user.greet()); // Output: Hi, Priya
console.log(user.greet.call({ name: "Kiran" })); // Output: Hi, Kiran

const greetRahul = user.greet.bind({ name: "Rahul" });
console.log(greetRahul()); // Output: Hi, Rahul

const team = {
  name: "CSK",
  players: ["Dhoni", "Jadeja"],
  list() {
    // The arrow function uses list()'s this, which is team.
    return this.players.map((p) => p + " plays for " + this.name);
  },
};
console.log(team.list()); // Output: ["Dhoni plays for CSK","Jadeja plays for CSK"]

class Wallet {
  constructor(balance) {
    this.balance = balance; // with new, this is the new object
  }
}
console.log(new Wallet(500).balance); // Output: 500

The classic bug, losing this:

js
const greet = user.greet; // just the function, no object attached
greet(); // in strict mode or a class: this is undefined -> TypeError

How it works

Check these rules in order:

  1. Called with new? this is the newly created object.
  2. Called with call, apply or bind? this is the object you passed.
  3. Called as a method, obj.fn()? this is obj, the thing before the dot.
  4. Plain call, fn()? this is undefined in strict mode (modules and classes are always strict). In old sloppy-mode scripts it is the global object.

Arrow functions skip all four rules. Their this is fixed to whatever this was where the arrow was created, and call, apply and bind cannot change it.

Real-world use

  • Passing a method as a callback, like button.addEventListener("click", cart.checkout), loses this. Fix it with cart.checkout.bind(cart) or an arrow wrapper () => cart.checkout().
  • In DOM event handlers written as normal functions, this is the element the listener is attached to.
  • In React class components, methods were bound in the constructor for this exact reason.

Common mistakes

  • Using an arrow function as an object method. this will not be the object.
  • Thinking this refers to the function itself or to where the function was written.
  • Extracting a method (const fn = obj.fn) and calling it alone.
  • Expecting bind to work on an arrow function.

What to say in the interview

"For normal functions, this is set by the call site. With new it is the new object. With call, apply or bind it is whatever I pass. With a method call like obj.fn() it is obj. With a plain function call it is undefined in strict mode. Arrow functions do not have their own this; they capture it from the surrounding scope, which is why they are handy for callbacks inside methods but a bad choice for object methods. Most this bugs come from passing a method as a callback, which I fix with bind or an arrow wrapper."

Follow-up questions

  • What is the difference between call, apply and bind?
  • What does this refer to inside a setTimeout callback?
  • Why should you not use arrow functions as object methods?

Go deeper

Read these once the basics above feel easy.

call(thisArg, a, b) and apply(thisArg, [a, b]) invoke the function immediately and differ only in how arguments are passed. bind(thisArg) returns a new function with this permanently fixed, even if it is later called as a method of another object. A bound function can still be used with new, and in that case the new object wins over the bound this. Class fields with arrow functions, such as handleClick = () => { ... }, create one bound function per instance, which is convenient but uses a little more memory than a shared prototype method.

#this#functions#objects#arrow-functions

Related questions

Practise more JavaScript questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open JavaScript quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.