What they do: All three manually control what this points to when calling functions.

The Core Problem They Solve:

javascript

let user = {
    name: "John",
    greet() {
        console.log(`Hi, I'm ${this.name}`);
    }
};
 
user.greet(); // "Hi, I'm John" ✓
 
let func = user.greet; // Extract method
func(); // "Hi, I'm undefined" ✗ - lost 'this'!

Problem: When you extract a method from an object, it loses its this connection.

call() - Immediate Execution with Manual this:

Syntax: func.call(thisValue, arg1, arg2, arg3)

javascript

function greet(greeting, punctuation) {
    console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}
 
let user = { name: "John" };
let admin = { name: "Admin" };
 
// Call immediately with different 'this' values
greet.call(user, "Hello", "!"); // "Hello, I'm John!"
greet.call(admin, "Hi", "."); // "Hi, I'm Admin."

Mental model: “Call this function RIGHT NOW with this specific this and these arguments”


apply() - Same as call() but Arguments as Array:

Syntax: func.apply(thisValue, [arg1, arg2, arg3])

javascript

function greet(greeting, punctuation) {
    console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}
 
let user = { name: "John" };
let args = ["Hello", "!"];
 
// Same result as call, but arguments in array
greet.apply(user, args); // "Hello, I'm John!"
 
// Useful when you have arguments in array form
let numbers = [1, 2, 3, 4, 5];
Math.max.apply(null, numbers); // 5 (find max of array)

Mental model: “Apply this function RIGHT NOW with this this and this array of arguments”


bind() - Create New Function with Locked this:

Syntax: let newFunc = func.bind(thisValue, arg1, arg2)

javascript

function greet(greeting, punctuation) {
    console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}
 
let user = { name: "John" };
 
// Create NEW function with locked 'this'
let boundGreet = greet.bind(user);
 
// Can call later - 'this' is permanently locked
boundGreet("Hello", "!"); // "Hello, I'm John!"
setTimeout(boundGreet, 1000, "Hi", "."); // Works in setTimeout!

Mental model: “Create a new function that ALWAYS uses this specific this

Quick Decision Tree:

Need to call RIGHT NOW?

  • Arguments separate? → Use call()
  • Arguments in array? → Use apply()

Need to call LATER with locked this?

  • Use bind() → Returns new function

Real-World Examples:

1. setTimeout Problem:

javascript

let user = {
    name: "John",
    sayHi() {
        console.log(`Hi, ${this.name}`);
    }
};
 
// Problem
setTimeout(user.sayHi, 1000); // "Hi, undefined"
 
// Solutions
setTimeout(user.sayHi.bind(user), 1000); // bind()
setTimeout(() => user.sayHi.call(user), 1000); // call()
setTimeout(() => user.sayHi(), 1000); // wrapper function

2. Method Borrowing:

javascript

function hash() {
    // 'arguments' isn't real array, borrow join method
    return [].join.call(arguments, ",");
}
 
hash(1, 2, 3); // "1,2,3"

3. Partial Application with bind:

javascript

function multiply(a, b) {
    return a * b;
}
 
let double = multiply.bind(null, 2); // Lock first argument
double(5); // multiply(2, 5) = 10
double(8); // multiply(2, 8) = 16

Interview Gotchas:

1. call vs apply memory trick:

javascript

// call = Comma separated
func.call(obj, arg1, arg2, arg3);
 
// apply = Array
func.apply(obj, [arg1, arg2, arg3]);

2. bind doesn’t execute immediately:

javascript

let user = { name: "John" };
function greet() { console.log(this.name); }
 
greet.call(user); // Executes: "John"
greet.bind(user); // Returns function, doesn't execute
greet.bind(user)(); // Now executes: "John"

3. bind creates permanent connection:

javascript

let user = { name: "John" };
let admin = { name: "Admin" };
 
function greet() { console.log(this.name); }
 
let boundGreet = greet.bind(user);
boundGreet.call(admin); // Still "John"! bind wins over call

4. bind with arguments (partial application):

javascript

function add(a, b, c) {
    return a + b + c;
}
 
let addFive = add.bind(null, 5); // Lock first argument
addFive(3, 2); // add(5, 3, 2) = 10

The Simple Rules:

  1. call/apply = Execute now with custom this
  2. bind = Create new function with locked this
  3. call = arguments separate
  4. apply = arguments in array
  5. bind = can lock arguments too (partial application)

Bottom line: All three let you control this. Use call/apply for immediate execution, bind for creating functions to call later.