The Magic of this, call(), apply(), and bind() in JavaScript

Imagine you're at a big JavaScript party.
Every function is a superhero with a special power. But here's the twist:
Their superpower only works properly when they know who invited them — who is actually calling them!
That mysterious "who" is this — the secret identity card that decides what the function can access and control.
But sometimes the wrong person shows up at the door… or no one shows up at all. Chaos!
Enter the three legendary sidekicks: call(), apply(), and bind() — they can force any superhero to work for whoever you want, whenever you want.
Grab your cape — let's meet the team! 🚀
1. this – The Ultimate Question: "Who Called Me?"
In JavaScript, this is not fixed. It depends on how the function is called.
Simple rule (the party rule):
this points to whoever is calling the function.
Let's see it in action with our hero squad.
2. this Inside Normal Functions
When you call a function normally (without any object), this points to… the global object (in browsers → window, in strict mode → undefined).
function whoAmI() {
console.log(this);
}
whoAmI(); // window (or undefined in strict mode)
The function is like: "Nobody invited me specially… so I'm just hanging with the whole party (global)."
3. this Inside Objects – The VIP Section
When a method is called on an object, this points to that object.
const ironMan = {
name: "Tony Stark",
suit: "Mark 85",
sayCatchphrase: function() {
console.log(`I am ${this.name} – genius, billionaire, playboy, philanthropist!`);
}
};
ironMan.sayCatchphrase();
// I am Tony Stark – genius, billionaire, playboy, philanthropist!
Here this = ironMan.
The function knows: "Tony called me — I'm in his suit!"
(These visuals show the confusion of this — sometimes it's pointing at the wrong hero!)
4–6. The Three Magic Spells: call(), apply(), bind()
Sometimes you want to borrow a method or force this to be someone else.
That's where the magic trio comes in.
call() – "Hey, work for THIS guy RIGHT NOW!"
call(thisArg, arg1, arg2, arg3, ...)
const thor = { name: "Thor", hammer: "Mjolnir" };
function introduce() {
console.log(`I am \({this.name} and I wield \){this.hammer || "nothing"}!`);
}
introduce.call(thor);
// I am Thor and I wield Mjolnir!
call immediately invokes the function and sets this to the first argument.
apply() – "Same as call, but arguments come in an ARRAY!"
apply(thisArg, [arg1, arg2, arg3, ...])
const hulk = { name: "Bruce Banner", power: "SMASH" };
function attack(move1, move2) {
console.log(`\({this.name} says: \){move1}! ${move2}!`);
}
attack.apply(hulk, ["HULK", "SMASH"]);
// Bruce Banner says: HULK! SMASH!
Perfect when you have arguments in an array (e.g., Math.max(...numbers) uses similar idea).
bind() – "Create a NEW superhero who ALWAYS works for THIS guy"
bind(thisArg, arg1, arg2, ...) → returns a new function, doesn't call it immediately.
const blackWidow = { name: "Natasha Romanoff", skill: "spy" };
const natashaIntro = introduce.bind(blackWidow);
natashaIntro();
// I am Natasha Romanoff and I wield nothing!
You can also pre-set arguments:
const partial = attack.bind(hulk, "PUNCH");
partial("KICK"); // Bruce Banner says: PUNCH! KICK!
7. Quick Comparison Table – The Superpower Summary
| Superpower | Invokes immediately? | Arguments passed as | Returns | Best For |
|---|---|---|---|---|
| call() | Yes | individual (comma) | result of function | Borrow method instantly |
| apply() | Yes | array | result of function | When args are already in array |
| bind() | No | individual (comma) | new bound function | Permanent this or partial application |
Mini Assignment – Avengers Training in Console!
- Create an object with a method using this:
const captain = {
name: "Steve Rogers",
shield: "Vibranium",
throwShield: function(target) {
console.log(`\({this.name} throws shield at \){target}!`);
}
};
- Borrow the method using call() for another hero:
const bucky = { name: "Bucky Barnes" };
captain.throwShield.call(bucky, "bad guy");
- Use apply() with array arguments:
captain.throwShield.apply(bucky, ["Hydra agent"]);
- Use bind() and store the function:
const buckyThrow = captain.throwShield.bind(bucky);
buckyThrow("Winter Soldier enemy");
Run in console — watch this change like magic!
Share your favorite hero version in the cohort group! 🦸♂️
Final Thought
this is like asking: "Who summoned me?"
call/apply/bind are the spells that answer: "YOU summoned me — now obey!"
Master them and you'll never fear lost context again.
Happy coding ✨
Which Avenger would YOU give bind() to? Comment below! 😄




