Skip to main content

Command Palette

Search for a command to run...

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

Published
13 min read

Introduction

Imagine you are in a chai shop in Delhi. The shop owner has a recipe for making chai. When you ask for chai, the owner makes it using their equipment and ingredients. The "chai shop owner" is the context, and "you" are the one requesting it. In JavaScript, this works the same way. It refers to the object that is calling the function.

In this blog, we will learn what this means, and three powerful methods (call(), apply(), and bind()) that let you control which object this refers to.


1. What this Means in JavaScript (Simple Explanation)

this refers to the object that is calling the function.

Think of this as an answer to the question: "Who is calling me?"

Simple Real-Life Analogy

Imagine you are a teacher, and you say "I will teach my class today."

  • If you are teaching at School A, "I" means "the teacher at School A"

  • If you are teaching at School B, "I" means "the teacher at School B"

The same person (you), but the meaning of "I" changes based on the context. Similarly, this changes based on who is calling the function.

Simple Code Example

const person = {
  name: "Ashish",
  greet: function() {
    console.log("Hello, my name is " + this.name);
  }
};

person.greet(); // Output: Hello, my name is Ashish

In this example, person is calling the greet function. So this refers to person, and this.name is "Ashish".

Global Context

When no object calls the function, this refers to the global object (in browsers, it is window):

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

sayName(); // this refers to global object (window in browsers)

2. this Inside Normal Functions

When a function is called directly (not as part of an object), this refers to the global object.

Example 1: Function Without an Object

function introduce() {
  console.log("My name is " + this.name);
}

introduce(); // this refers to global object, this.name is undefined

In strict mode, this would be undefined:

"use strict";

function introduce() {
  console.log(this); // undefined in strict mode
}

introduce();

Example 2: Variable in Global Scope

let globalName = "World";

function greet() {
  console.log("Hello, " + this.name); // Tries to access global.name
}

greet(); // Output: Hello, undefined

The function cannot access variables directly through this in the global scope.

Key Point

In normal functions, this is determined by how the function is called, not where it is defined.

let person = {
  name: "Ashish"
};

function getName() {
  return this.name;
}

// Called as a normal function
console.log(getName()); // Output: undefined (this is global)

// Called through the person object
console.log(person.getName = getName); // We will assign it next

3. this Inside Objects

When a function is called as a method of an object (using dot notation), this refers to that object.

Example 1: Simple Object with Method

JavaScript

const student = {
  name: "Ashish",
  age: 20,
  greet: function() {
    console.log("Hello, I am " + this.name);
  }
};

student.greet(); // Output: Hello, I am Ashish

Here, student calls the greet function, so this refers to student.

Example 2: Accessing Multiple Properties

JavaScript

const college = {
  name: "IIIT Bangalore",
  founded: 2009,
  getInfo: function() {
    return this.name + " was founded in " + this.founded;
  }
};

console.log(college.getInfo());
// Output: IIIT Bangalore was founded in 2009

Example 3: Modifying Object Properties with this

JavaScript

const bank = {
  accountBalance: 10000,
  deposit: function(amount) {
    this.accountBalance += amount;
    console.log("New balance: " + this.accountBalance);
  },
  withdraw: function(amount) {
    this.accountBalance -= amount;
    console.log("New balance: " + this.accountBalance);
  }
};

bank.deposit(5000);   // Output: New balance: 15000
bank.withdraw(2000);  // Output: New balance: 13000

Important: this is Dynamic

The value of this depends on how the function is called, not where it is defined:

const person1 = {
  name: "Ashish",
  greet: function() {
    console.log("Hello, I am " + this.name);
  }
};

const person2 = {
  name: "Priya"
};

// Calling through person1
person1.greet(); // Output: Hello, I am Ashish

// Calling through person2
person2.greet = person1.greet;
person2.greet(); // Output: Hello, I am Priya (this refers to person2 now!)

Even though we are using the same function, this changes based on which object calls it!


4. What call() Does

The call() method lets you call a function and specify what this should refer to. It executes the function immediately.

Syntax

functionName.call(objectToUseAsThis, arg1, arg2, ...);

Example 1: Using call() to Set this

function introduce() {
  console.log("My name is " + this.name);
}

const ashish = { name: "Ashish" };
const priya = { name: "Priya" };

// Call the function with ashish as this
introduce.call(ashish); // Output: My name is Ashish

// Call the function with priya as this
introduce.call(priya);  // Output: My name is Priya

Without call(), we could not reuse this function for different objects. With call(), we can!

Example 2: call() with Arguments

function calculateAge(currentYear) {
  return currentYear - this.birthYear;
}

const ashish = { birthYear: 2005 };
const priya = { birthYear: 2004 };

let ashishAge = calculateAge.call(ashish, 2026); // Output: 21
let priyaAge = calculateAge.call(priya, 2026);   // Output: 22

console.log(ashishAge); // Output: 21
console.log(priyaAge);  // Output: 22

Arguments after the object are passed to the function.

Example 3: College Enrollment

function enrollStudent(semester, course) {
  console.log(this.name + " enrolled in " + course + " in semester " + semester);
}

const student1 = { name: "Ashish" };
const student2 = { name: "Priya" };

enrollStudent.call(student1, 4, "Data Structures");
// Output: Ashish enrolled in Data Structures in semester 4

enrollStudent.call(student2, 3, "Web Development");
// Output: Priya enrolled in Web Development in semester 3

Example 4: Borrowing Methods from Objects

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

const pet = {
  name: "Buddy"
};

// Borrow the greet method from person for pet
person.greet.call(pet, "Woof"); // Output: Woof, Buddy

Even though pet does not have a greet method, we can use the one from person!


5. What apply() Does

The apply() method is similar to call(), but instead of listing arguments one by one, you pass them as an array.

Syntax

functionName.apply(objectToUseAsThis, [arg1, arg2, ...]);

Example 1: Using apply()

function introduce(greeting, punctuation) {
  console.log(greeting + ", my name is " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// Using call (arguments one by one)
introduce.call(ashish, "Hello", "!");
// Output: Hello, my name is Ashish!

// Using apply (arguments in an array)
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, my name is Ashish!

Both produce the same result. The difference is how you pass arguments.

Example 2: Finding Maximum with apply()

A common use of apply() is to pass array elements as arguments:

const numbers = [10, 20, 50, 30, 5];

// Math.max expects individual arguments, not an array
// Without apply, this would not work:
// console.log(Math.max(numbers)); // Output: NaN

// With apply, we convert the array to individual arguments:
let max = Math.max.apply(null, numbers);
console.log(max); // Output: 50

Example 3: Adding Multiple Numbers

function addNumbers(a, b, c, d) {
  return a + b + c + d;
}

const numbers = [10, 20, 30, 40];

let sum = addNumbers.apply(null, numbers);
console.log(sum); // Output: 100

Important: The First Argument (null or object)

When the object does not matter (or there is no specific object to use), pass null:

function add(a, b) {
  return a + b;
}

let result = add.apply(null, [5, 10]); // null means "no specific object"
console.log(result); // Output: 15

6. What bind() Does

The bind() method creates a new function with a fixed this value. Unlike call() and apply(), bind() does NOT execute the function immediately. It returns a new function that you can call later.

Syntax

const newFunction = functionName.bind(objectToUseAsThis, arg1, arg2, ...);

Example 1: Using bind()

function greet(greeting) {
  console.log(greeting + ", " + this.name);
}

const ashish = { name: "Ashish" };

// Create a new function with ashish as this
const ashishGreet = greet.bind(ashish);

// Call it later
ashishGreet("Hello"); // Output: Hello, Ashish
ashishGreet("Hi");    // Output: Hi, Ashish

Notice that we create the function first with bind(), then call it later. This is different from call() and apply(), which execute immediately.

Example 2: bind() with Preset Arguments

You can also preset some arguments:

function calculateFee(baseFee, discountPercentage) {
  let discount = baseFee * (discountPercentage / 100);
  return baseFee - discount;
}

const student = { name: "Ashish" };

// Create a function with preset discount of 10%
const calculateStudentFee = calculateFee.bind(null, 50000, 10);

let fee = calculateStudentFee();
console.log(fee); // Output: 45000

Example 3: bind() in Event Handlers

A common use of bind() is in event handlers:

const person = {
  name: "Ashish",
  clickHandler: function() {
    console.log("Button clicked by " + this.name);
  }
};

// Without bind, this would refer to the button element
// With bind, this refers to person
const button = document.querySelector("button");
button.addEventListener("click", person.clickHandler.bind(person));

(This is more advanced, but shows a real-world use case.)

Example 4: bind() for Later Execution

JavaScript

function greetStudent(greeting, subject) {
  console.log(greeting + " " + this.name + ", you are learning " + subject);
}

const ashish = { name: "Ashish" };
const priya = { name: "Priya" };

// Create bound functions
const greetAshish = greetStudent.bind(ashish);
const greetPriya = greetStudent.bind(priya);

// Use them later
greetAshish("Welcome", "JavaScript");  // Output: Welcome Ashish, you are learning JavaScript
greetPriya("Hi", "Python");            // Output: Hi Priya, you are learning Python

7. Difference Between call(), apply(), and bind()

Now let's compare these three powerful methods.

Quick Comparison

Method Executes Immediately Arguments Returns
call() Yes One by one: arg1, arg2 Function result
apply() Yes As array: [arg1, arg2] Function result
bind() No One by one: arg1, arg2 New function (not executed)

Side-by-Side Examples

call() Example

function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// call executes immediately with arguments one by one
introduce.call(ashish, "Hello", "!");
// Output: Hello, Ashish! (executed immediately)

apply() Example

function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// apply executes immediately with arguments as array
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, Ashish! (executed immediately)

bind() Example

function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// bind creates a new function (not executed yet)
const ashishIntroduce = introduce.bind(ashish, "Hello", "!");

// Call it later
ashishIntroduce();
// Output: Hello, Ashish! (executed when we call it)

When to Use Each

Use call() When

You want to execute a function immediately with a specific this and arguments one by one:

function sayHello(greeting) {
  console.log(greeting + ", " + this.name);
}

const person = { name: "Ashish" };

sayHello.call(person, "Hello"); // Execute now

Use apply() When

You want to execute a function immediately with a specific this but have arguments in an array:

function sum(a, b, c) {
  return a + b + c;
}

const numbers = [10, 20, 30];
let result = sum.apply(null, numbers); // Execute now with array

Use bind() When

You want to create a new function to use later:

function calculateAge(year) {
  return 2026 - this.birthYear - year;
}

const person = { birthYear: 2005 };

// Create for later use
const getPersonAge = calculateAge.bind(person, 5);

// Use it later
console.log(getPersonAge()); // Output: 16

Detailed Comparison Table

Aspect call() apply() bind()
Executes immediately Yes Yes No
Returns Function result Function result New function
Arguments format One by one: arg1, arg2 Array: [arg1, arg2] One by one: arg1, arg2
First parameter Object for this Object for this Object for this
Use case Quick execution Array arguments Store for later
Example fn.call(obj, 1, 2) fn.apply(obj, [1, 2]) fn.bind(obj, 1, 2)

Visual Representation

How call() Works

Function Definition
        |
        v
    sayHi()
        |
        +------ call(person1) ------> Execute with person1 as this
        |
        +------ call(person2) ------> Execute with person2 as this
        
Result: Function executes immediately with specified this

How apply() Works

Function Definition
        |
        v
    addNumbers()
        |
        +------ apply(null, [10, 20]) ------> Execute with array as arguments
        
Result: Function executes immediately, array unpacked to arguments

How bind() Works

Function Definition
        |
        v
    greet()
        |
        +------ bind(ashish, "Hello") ------> Create NEW function
        |
        v
   boundGreet
        |
        +------ Call later when needed ------> Execute
        
Result: New function created, not executed until called

Summary

  1. this refers to the object that is calling the function

    • In normal functions, this is the global object

    • In object methods, this refers to that object

  2. call() executes a function immediately with a specific this and arguments one by one

    • Syntax: fn.call(object, arg1, arg2)

    • Use when you need immediate execution

  3. apply() executes a function immediately with a specific this and arguments as an array

    • Syntax: fn.apply(object, [arg1, arg2])

    • Use when arguments are in an array

  4. bind() creates a new function with a fixed this value for later use

    • Syntax: fn.bind(object, arg1, arg2)

    • Use when you need to store a function for later

  5. Key differences:

    • call() and apply() execute immediately

    • bind() creates a new function

    • call() and bind() use arguments one by one

    • apply() uses arguments as an array

  6. Real-world uses:

    • Borrowing methods from other objects

    • Creating specialized versions of functions

    • Using in event handlers and callbacks

    • Working with array methods like Math.max()