Skip to main content

Command Palette

Search for a command to run...

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

Updated
โ€ข5 min read
The Magic of this, call(), apply(), and bind() in JavaScript
A

I'm a Software engineer and recently graduated (2025) in computer engineering, I'm more into Fullstack Developement using Angular, Nodejs, Express js, Mongodb, currently getting my hands on React js and Next js. Connect me on Linkedin here: https://linkedin.com/in/amanpatel2529

Hey everyone, Aman here! ๐Ÿ‘‹

If there is one keyword in JavaScript that makes developers scratch their heads, it's this. It can feel like a shape-shifter, changing its identity depending on where and how you use it.

But don't worry! Today, we are going to strip away the confusion. Weโ€™ll look at what this actually means, and then we will explore three magical methodsโ€”call(), apply(), and bind()โ€”that let us control exactly how this behaves.

As always, open up your browser's console (F12 or Right-Click -> Inspect -> Console) and code along with me!


๐Ÿ•ต๏ธโ€โ™‚๏ธ What exactly is this?

In simple terms, this refers to "who is calling the function right now."

Think of the word "this" in English. If I say, "I own this laptop," the word "this" points to the laptop currently in front of me. If you say it, it points to your laptop. The word stays the same, but the object it points to changes depending on who is talking.

JavaScript's this works exactly the same way. Its value depends entirely on the context of how a function is called.

this inside a Normal Function

If you just call a regular function out in the open, this defaults to the global object (which is the window object in your browser).

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

showThis(); // Output: Window {...} (The global browser object)

this inside an Object

When a function is stored inside an object (making it a method), this points to the object that owns the method. The object is the one "calling" the function!

const user = {
  name: "Aman",
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

user.greet(); // Output: Hello, my name is Aman

Here, user called the greet function, so this equals user.


๐Ÿช„ The Magic Trio: call(), apply(), and bind()

Sometimes, we want to borrow a method from one object and use it on a completely different object. We want to manually tell JavaScript, "Hey, I know this function belongs to Object A, but I want you to pretend that Object B is calling it."

This is where our magic trio comes in!

1. call(): The Direct Borrower

The call() method immediately invokes a function, but lets you pass in the object that should be treated as this. Any extra arguments are passed in one by one, separated by commas.

const person1 = { name: "Alice" };
const person2 = { name: "Bob" };

function introduce(greeting, punctuation) {
  console.log(`\({greeting}, I am \){this.name}${punctuation}`);
}

// We borrow the 'introduce' function and manually set 'this' to person1
introduce.call(person1, "Hi", "!"); // Output: Hi, I am Alice!

// Now we do it for person2
introduce.call(person2, "Hello", "."); // Output: Hello, I am Bob.

2. apply(): The Array Borrower

apply() does the exact same thing as call(). It immediately runs the function and lets you set this.

The only difference is how you pass the extra arguments. While call() takes them separated by commas, apply() requires you to pass them in as an array.

const hero = { name: "Batman" };

function action(action1, action2) {
  console.log(`\({this.name} will \){action1} and ${action2}!`);
}

// With call(), we pass arguments normally:
action.call(hero, "punch", "kick");

// With apply(), we pass an array of arguments:
action.apply(hero, ["punch", "kick"]); // Output: Batman will punch and kick!

Pro Tip: apply() is super useful when you already have an array of data that you want to pass into a function!

3. bind(): The Saver

While call() and apply() run the function immediately, bind() does not.

Instead, bind() creates a brand new function with this permanently locked in, and returns it to you so you can use it later.

const player = { name: "Luigi" };

function jump() {
  console.log(`${this.name} jumped high!`);
}

// We bind the function to 'player', but it doesn't run yet.
const playerJump = jump.bind(player);

// Later in the code, when we are ready...
playerJump(); // Output: Luigi jumped high!

๐Ÿ“Š Summary: The Cheat Sheet

Here is a quick comparison table to help you remember the differences:

Method

Does it run immediately?

How does it take arguments?

Best used when...

call()

Yes

Comma-separated (arg1, arg2)

You know the exact arguments and need to run it now.

apply()

Yes

Inside an Array ([arg1, arg2])

Your arguments are already stored in an array.

bind()

No (Returns a new function)

Comma-separated

You want to save the function to execute later (like in an event listener).

๐Ÿ‘จโ€๐Ÿ’ป Your Turn: The Assignment!

Ready to practice your borrowing skills? Open your console and try this out:

  1. Create an object called car with a property brand (e.g., "Tesla") and a method called startEngine that prints "The [brand] engine started!" using this.

  2. Create a second object called bike with just a brand property (e.g., "Yamaha").

  3. Use call() to borrow the startEngine method from car and use it on bike.

  4. Write a standalone function called calculateSpeed(distance, time) that prints "[brand] speed is [result]".

  5. Use apply() to run calculateSpeed on the car object, passing the distance and time as an array.

  6. Use bind() to lock calculateSpeed to the bike object, store it in a variable called bikeSpeed, and then execute it!

Understanding how to manipulate context will elevate your JavaScript skills to a whole new level. It's a foundational concept for React and modern JS frameworks!