Going DeeperPro· 45 min read

The this Keyword & call / apply / bind

The most slippery word in JavaScript. What this points to depends on HOW a function is called — and three tools let you set it deliberately.

What you will learn

  • State the rule for what this refers to
  • Explain why this is lost in callbacks
  • Set this on purpose with call, apply and bind

this depends on HOW you call the function

You met this briefly inside object methods, where this.name meant "this object’s name". The full truth: this is not fixed when you write the function — it is decided at the moment you call it, based on how you call it. The same function can have a different this each time.

The most common, reliable case: when you call a function as a method (object.method()), this is that object — the thing before the dot.

Called as user.greet(), this is user
<script>
  const user = {
    name: "Asha",
    greet() {
      return "Hi, I am " + this.name;   // this = the object before the dot
    }
  };
  document.write(user.greet());
</script>
Live preview

Because we call user.greet(), the part before the dot is user, so inside greet the word this means user and this.name is "Asha". The rule is literally "look at what is left of the dot at call time".

Note: Output: Hi, I am Asha

How this gets "lost" in callbacks

The headache: if you pull a method out and call it on its own (no object before the dot — for example when a timer or event later calls it), this is no longer your object. Inside a plain function called that way, this is undefined (in strict mode), so this.name breaks.

this is lost: the callback was not called on user
<p id="out"></p>
<script>
  const user = {
    name: "Asha",
    greetLater() {
      // setTimeout calls this plain function with NO object before the dot
      setTimeout(function () {
        document.getElementById("out").textContent = "Hi, I am " + this.name;
      }, 300);
    }
  };
  user.greetLater();
</script>
Live preview

We call user.greetLater(), but inside, the function handed to setTimeout is later called by the timer, not as user.something(). With no object before the dot, its this is not user, so this.name comes out empty (or "undefined"). This "lost this" is one of the most common JavaScript bugs.

Note: Output: Hi, I am undefined (Or just "Hi, I am " — the callback’s this was not the user object.)

Tip: The easy modern fix: use an arrow function for the callback. Arrow functions do not get their own this — they borrow it from the surrounding code. Changing function () {…} to () => {…} above would correctly keep this as user.

call, apply & bind — set this on purpose

When you need to control this deliberately, three built-in methods let you choose it. They all take the object you want this to be as their first argument.

MethodWhat it doesRuns the function?
fn.call(obj, a, b)Run fn now with this = obj, args listed one by oneYes, immediately
fn.apply(obj, [a, b])Same as call, but args given as an arrayYes, immediately
fn.bind(obj)Returns a NEW function with this permanently set to objNo — call it later

Here is one greet function reused on two different objects with call, and a permanently-bound version made with bind.

call runs now; bind makes a reusable bound function
<script>
  function greet(greeting) {
    return greeting + ", I am " + this.name;
  }
  const asha = { name: "Asha" };
  const ravi = { name: "Ravi" };

  document.write(greet.call(asha, "Hello") + "<br>");   // this = asha
  document.write(greet.call(ravi, "Hi") + "<br>");      // this = ravi

  const greetAsha = greet.bind(asha);                   // this locked to asha
  document.write(greetAsha("Namaste"));                 // call later
</script>
Live preview

Reading it line by line:

  1. greet uses this.name, but is written without any fixed object.
  2. greet.call(asha, "Hello") runs greet right now with this set to asha, so this.name is "Asha".
  3. greet.call(ravi, "Hi") reuses the same function with this set to ravi — one function, two objects.
  4. greet.bind(asha) does not run anything; it returns a brand-new function with this permanently glued to asha.
  5. We store that as greetAsha and call it later — it always uses asha. (apply is identical to call but takes its arguments as an array.)

Note: Output: Hello, I am Asha Hi, I am Ravi Namaste, I am Asha

Watch out: Remember the difference: call and apply invoke immediately; bind returns a new function to use later. bind is the classic way to keep this correct when passing a method as a callback.

Q. What does fn.bind(obj) return?

Answer: bind does not run the function. It returns a new function whose this is permanently fixed to obj, which you can call whenever you like. call and apply, by contrast, run the function immediately.

✍️ Practice

  1. Write a method that uses this, pull it into a variable, call it alone, and watch this break — then fix it with bind.
  2. Use call to run one describe() function against two different objects.

🏠 Homework

  1. Write a short explainer: the four ways this is decided (method call, plain function call, call/apply/bind, arrow function) with a one-line example of each.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →