Skip to main content

Command Palette

Search for a command to run...

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

Updated
8 min read

What is this?

this = "Who called this function?"

Simple as that.

const person = {
  name: "Alice",
  greet: function() {
    console.log("Hello, I'm " + this.name);
  }
};

person.greet(); // "Hello, I'm Alice"

this refers to person because person called the greet method.

Think of this as a pronoun.

"I am Alice" → this.name is "Alice"

The value of this depends on how the function is called.


this in Different Contexts

1. In a regular function (standalone)

function showThis() {
  console.log(this);
}

showThis(); // Window object (in browser) or undefined (strict mode)

No specific caller = this is the global object.

2. Inside an object method

const user = {
  name: "Bob",
  showName: function() {
    console.log(this.name);
  }
};

user.showName(); // "Bob"

user called the method → this = user

3. In arrow functions (special case)

const person = {
  name: "Charlie",
  greet: () => {
    console.log(this.name); // undefined or window.name
  }
};

person.greet();

Arrow functions don't have their own this. They inherit from surrounding scope.

Rule: Use regular functions for object methods if you need this.


Real-World Example

const car = {
  brand: "Toyota",
  model: "Camry",
  start: function() {
    console.log(this.brand + " " + this.model + " is starting");
  }
};

car.start(); // "Toyota Camry is starting"

this.brand = car.brand = "Toyota"

this.model = car.model = "Camry"

this changes based on the caller.

const showInfo = car.start;

showInfo(); // "undefined undefined is starting"

Why? showInfo() is called standalone. No object context.

this becomes global object (no brand or model there).

This is where call(), apply(), and bind() help.


What is call()?

call() lets you call a function and manually set this.

Syntax:

functionName.call(thisValue, arg1, arg2, ...)

Example:

const person1 = {
  name: "Alice"
};

const person2 = {
  name: "Bob"
};

function greet() {
  console.log("Hello, I'm " + this.name);
}

greet.call(person1); // "Hello, I'm Alice"
greet.call(person2); // "Hello, I'm Bob"

call() sets this to the object you pass.

With arguments:

function introduce(age, city) {
  console.log("I'm " + this.name + ", " + age + " years old from " + city);
}

const person = { name: "Alice" };

introduce.call(person, 25, "Mumbai");
// "I'm Alice, 25 years old from Mumbai"

Pattern:

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

What is apply()?

apply() is like call(), but arguments are passed as an array.

Syntax:

functionName.apply(thisValue, [arg1, arg2, ...])

Example:

function introduce(age, city) {
  console.log("I'm " + this.name + ", " + age + " years old from " + city);
}

const person = { name: "Bob" };

introduce.apply(person, [30, "Delhi"]);
// "I'm Bob, 30 years old from Delhi"

call() vs apply():

// call - arguments individually
introduce.call(person, 25, "Mumbai");

// apply - arguments as array
introduce.apply(person, [25, "Mumbai"]);

When to use apply():

When you already have arguments in an array.

const person = { name: "Charlie" };
const details = [28, "Bangalore"];

introduce.apply(person, details);
// "I'm Charlie, 28 years old from Bangalore"

What is bind()?

bind() creates a new function with this permanently set.

It doesn't call the function immediately.

Syntax:

const newFunc = functionName.bind(thisValue, arg1, arg2, ...)

Example:

const person = {
  name: "Alice",
  greet: function() {
    console.log("Hello, I'm " + this.name);
  }
};

const greetFunc = person.greet;

greetFunc(); // "Hello, I'm undefined" (lost context)

const boundGreet = person.greet.bind(person);

boundGreet(); // "Hello, I'm Alice" (context preserved)

Use case: Event handlers

const button = {
  text: "Click me",
  handleClick: function() {
    console.log("Button says: " + this.text);
  }
};

// Without bind
// document.getElementById('btn').addEventListener('click', button.handleClick);
// "Button says: undefined" (this = button element, not our object)

// With bind
// document.getElementById('btn').addEventListener('click', button.handleClick.bind(button));
// "Button says: Click me" (this = button object)

bind() with arguments:

function multiply(a, b) {
  return a * b;
}

const double = multiply.bind(null, 2);

console.log(double(5)); // 10 (2 * 5)
console.log(double(3)); // 6  (2 * 3)

First argument to bind() is this. Rest are pre-filled arguments.


call() vs apply() vs bind()

Method Arguments Execution Returns
call() Individual: func.call(this, a, b) Immediate Function result
apply() Array: func.apply(this, [a, b]) Immediate Function result
bind() Individual: func.bind(this, a, b) Later (manual) New function

Visual comparison:

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

const person = { name: "Alice" };

// call - runs immediately, individual args
introduce.call(person, 25, "Mumbai");

// apply - runs immediately, array args
introduce.apply(person, [25, "Mumbai"]);

// bind - returns new function, call it later
const boundIntroduce = introduce.bind(person, 25, "Mumbai");
boundIntroduce(); // Call it when needed

Practical Examples

Example 1: Method borrowing with call()

const person1 = {
  name: "Alice",
  age: 25,
  introduce: function() {
    console.log("I'm " + this.name + ", " + this.age + " years old");
  }
};

const person2 = {
  name: "Bob",
  age: 30
};

// Borrow person1's method for person2
person1.introduce.call(person2);
// "I'm Bob, 30 years old"

Example 2: Math operations with apply()

const numbers = [5, 10, 15, 20, 3];

// Find max using apply
const max = Math.max.apply(null, numbers);
console.log(max); // 20

// Find min
const min = Math.min.apply(null, numbers);
console.log(min); // 3

Math.max() expects individual arguments, not an array.

apply() converts array to individual arguments.

Example 3: Creating reusable functions with bind()

function calculatePrice(price, taxRate) {
  return price + (price * taxRate);
}

// Pre-set tax rate for India
const calculateIndianPrice = calculatePrice.bind(null, 100);

console.log(calculateIndianPrice(0.18)); // 118
console.log(calculateIndianPrice(0.12)); // 112

// Better: curry-style
function multiply(a) {
  return function(b) {
    return a * b;
  };
}

const double = multiply(2);
const triple = multiply(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

Practice Assignment

Task: Explore this, call(), apply(), and bind()

// 1. Create object with method using this
const student = {
  name: "Alice",
  grade: "A",
  showDetails: function() {
    console.log(this.name + " got grade " + this.grade);
  }
};

student.showDetails(); // "Alice got grade A"

// 2. Borrow method using call()
const student2 = {
  name: "Bob",
  grade: "B"
};

student.showDetails.call(student2); // "Bob got grade B"

// 3. Function with arguments
function displayInfo(age, city) {
  console.log(this.name + ", " + age + " years old, from " + city);
}

// Using call
displayInfo.call(student, 20, "Mumbai");
// "Alice, 20 years old, from Mumbai"

// Using apply
displayInfo.apply(student2, [22, "Delhi"]);
// "Bob, 22 years old, from Delhi"

// 4. Using bind
const boundDisplay = displayInfo.bind(student, 20, "Mumbai");

boundDisplay(); // "Alice, 20 years old, from Mumbai"
// Can call multiple times
boundDisplay();
boundDisplay();

// 5. Real-world: Array max/min
const scores = [85, 92, 78, 95, 88];

const maxScore = Math.max.apply(null, scores);
const minScore = Math.min.apply(null, scores);

console.log("Max:", maxScore); // 95
console.log("Min:", minScore); // 78

Common Mistakes

Losing this context

const person = {
  name: "Alice",
  greet: function() {
    console.log(this.name);
  }
};

const greet = person.greet;
greet(); // undefined (lost context)

Use bind() to preserve context

const greet = person.greet.bind(person);
greet(); // "Alice"

Using arrow function for object methods

const person = {
  name: "Bob",
  greet: () => {
    console.log(this.name); // undefined
  }
};

Use regular function

const person = {
  name: "Bob",
  greet: function() {
    console.log(this.name); // "Bob"
  }
};

Confusing call and apply syntax

func.call(obj, [1, 2, 3]); // Wrong! Passes array as single arg
func.apply(obj, 1, 2, 3);  // Wrong! apply needs array

Remember the difference

func.call(obj, 1, 2, 3);    // Individual args
func.apply(obj, [1, 2, 3]); // Array of args

Quick Reference

this:

const obj = {
  method: function() {
    console.log(this); // obj
  }
};

call():

func.call(thisValue, arg1, arg2, arg3)
// Calls immediately, individual arguments

apply():

func.apply(thisValue, [arg1, arg2, arg3])
// Calls immediately, array arguments

bind():

const newFunc = func.bind(thisValue, arg1, arg2)
// Returns new function, call later

Memory trick:

  • Call = Comma separated (individual args)

  • Apply = Array (array args)

  • Bind = Bound (creates bound function)


You Now Understand this and Function Methods

What this means (the caller)
this in different contexts
call() - set this and call immediately
apply() - like call() but with array args
bind() - create new function with fixed this
When to use each

When to Use Each

Use call() when:

  • Borrowing methods

  • Setting this with few arguments

Use apply() when:

  • Arguments are already in an array

  • Using with Math.max/min

Use bind() when:

  • Event handlers

  • Creating reusable functions

  • Preserving context for later

Modern Alternative

Arrow functions often replace bind() for preserving context:

// Old way with bind
setTimeout(obj.method.bind(obj), 1000);

// Modern way with arrow
setTimeout(() => obj.method(), 1000);

But call() and apply() are still essential for method borrowing.

Functions are powerful in JavaScript.

Master this, call(), apply(), and bind() to unlock that power.


Leveling up your JavaScript? Follow for more advanced fundamentals.