Sitemap
Abhijit Patil

Abhijit Patil

Mastering call, apply, and bind — Practical Guide to Control "this" (Part 2)

4 min readApr 8, 2026

--

In Part 1, we understood how this works and why it often behaves unexpectedly.
You can check part 1 : https://medium.com/@abhijitpatil669/understanding-this-in-javascript-a-practical-guide-to-stop-the-confusion-fd092b274785

Now comes the real question:

What do we do when this goes wrong?
How do we control it?

That’s exactly where call, apply, and bind comes in.

By the end of this article, you should be able to:

  • Recognize when this will break
  • Fix it confidently
  • Understand what happens internally
  • Solve interview questions easily

First, Build the Right Mental Model

Before jumping into the methods, get this clear:

JavaScript decides this at execution time, based on how a function is called.

So when this feels wrong, it’s usually not a bug—it’s just JavaScript doing what it’s supposed to.

call, apply, and bind give you a way to take control when needed.

The Problem Pattern (Very Important)

A lot of real-world bugs come from this pattern:

const obj = {
name: "JS",
print() {
console.log(this.name);
}
};

const fn = obj.print;
fn();

What’s actually happening?

Call stack will call “fn()” Not “obj.print()”

So:

  • this is lost
  • Output: undefined

Key Insight

Whenever a function is called without an object, this is usually not what you expect.

1. call() — Execute Immediately with Correct this

Think of it as:

“Run this function right now with this object”

Example:

function greet() {
console.log(this.name);
}

const user = { name: "Abhijit" };

greet.call(user);

What’s happening internally?

Instead of “greet()”

It behaves like:

greet.call(user);
// similar to:
user.greet();

Call Stack View: greet() (with this = user)

When to use:

  • Reusing functions across objects
  • Immediate execution
  • Simple scenarios

2. apply() — Same as call, but with Array

Think of it as:

“Run this function now with this object and arguments as an array”

Example:

function introduce(age, city) {
console.log(this.name, age, city);
}

const user = { name: "Abhijit" };

introduce.apply(user, [25, "Pune"]);

When to use:

  • When arguments come as an array (API data, dynamic input)

3. bind() — Fix this for Later

Think of it as:

“Create a new function where this is permanently fixed”

Get Abhijit Patil’s stories in your inbox

Join Medium for free to get updates from this writer.

Example:

function greet() {
console.log(this.name);
}

const user = { name: "Abhijit" };

const fn = greet.bind(user);

fn();

What’s happening internally?

const fn = greet.bind(user);

Creates a new function like:

function () {
return greet.call(user);
}

Call Stack View:

fn()
-> greet() with this = user

When to use:

  • Callbacks
  • Event handlers
  • Async code
  • Anywhere this might get lost

Real-World Case 1: setTimeout Bug

const user = {
name: "Abhijit",
greet() {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};

Execution Flow:

  1. greet() runs with this = user
  2. setTimeout registers callback
  3. After 1 second: “callback()” NOT “user.callback()”

Problem:

  • this becomes window or undefined

Fix:

setTimeout(function () {
console.log(this.name);
}.bind(this), 1000);

Learning:

  • When function runs later (async), this can be lost
  • Use bind or arrow functions

Real-World Case 2: Event Handlers

const button = {
text: "Click",
handleClick() {
console.log(this.text);
}
};

document.addEventListener("click", button.handleClick);

What happens?

handleClick()

"this" is lost

Fix:

document.addEventListener(
"click",
button.handleClick.bind(button)
);

Learning:

  • Always bind when passing object methods as event handlers

Pattern Recognition (Most Important Skill)

These patterns break this:

setTimeout(obj.method, 1000);
const fn = obj.method;
return obj.method;

Fix using:

.bind(obj)

OR

() => obj.method()

Execution-Level Understanding

Without bind:

callback()
-> this = window

With bind:

callback()
-> behaves like:
callback.call(user)
-> this = user

When to Use What

Press enter or click to view image in full size

Practice (Think Before Answer)

function show() {
console.log(this.name);
}

const user = { name: "JS" };

setTimeout(show, 1000);

// Fix it
const obj = {
name: "JS",
print() {
console.log(this.name);
}
};

const fn = obj.print;
fn();

// fix it

Tricky Interview Questions

var name = "Global";

const obj = {
name: "Object",
getName() {
return this.name;
}
};

const fn = obj.getName;
console.log(fn());


// Answer:
// Browser → "Global"
// Node → undefined
const obj = {
name: "JS",
print() {
console.log(this.name);
}
};

setTimeout(obj.print, 1000);

// OUTPUT : Undefined

// FIX:
setTimeout(obj.print.bind(obj), 1000);
const obj = {
name: "JS",
print() {
return function () {
console.log(this.name);
};
}
};

obj.print()();

// Output: undefined
function show() {
console.log(this.name);
}

const user = { name: "A" };

const fn = show.bind(user);
fn.call({ name: "B" });

// Output: "A"
// Reason: bind cannot be overridden
function add(a, b) {
console.log(this.name, a + b);
}

const obj = { name: "Test" };

add.apply(obj, [1, 2]);

// Output: "Test 3"
const obj = {
name: "JS",
print() {
console.log(this.name);
}
};

(obj.print = obj.print)();

// Output: undefined
// Reason: assignment breaks reference
const obj = {
name: "JS",
print() {
console.log(this.name);
}
};

const fn = obj.print.bind(obj);
setTimeout(fn, 1000);

//Output: "JS"
// Reason: bind permanently fixes this

Execution Mindset

Whenever you see a function, ask:

How is it being called?

Case 1:
fn()
-> this lost

Case 2:
obj.fn()
-> this = obj

Case 3:
fn.bind(obj)()
-> this = obj

Final Takeaway

  • this breaks when a function loses its object
  • call and apply fix it immediately
  • bind fixes it permanently
  • Most bugs happen in async or detached functions

Final Mental Model

Whenever you see a function, ask:

“How will this function be called?”

If it's: callback()
this is gone

If it’s:obj.method()
this is safe

Once you start spotting these patterns, you won’t just understand this — you’ll be able to predict it.

--

--