DEV Community

Cover image for The Magic of this, call(), apply(), and bind()
SATYA SOOTAR
SATYA SOOTAR

Posted on

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

Hello readers 👋, welcome back to 10th blog in this JavaScript series.

Imagine you're at a party, and someone shouts, "Hey, come here!" Who will respond? It depends on who is calling and who they're looking at.

In JavaScript, the this keyword works exactly like that. It's a special word that refers to the context – the object that is currently "calling" the function.

But sometimes, you want to control who this refers to. That's where the magical trio – call(), apply(), and bind() – come into play.

In this blog, we'll demystify this and learn how to bend it to our will using these methods.

What is this in JavaScript? (The Simple Explanation)

this is a keyword that refers to the object that is executing the current function.

Think of it like this: when a function is called, this is like a secret note that tells the function, "Hey, you're working for this object right now."

Simple rule:

this refers to who is calling the function.

this Inside Normal Functions

When you use this inside a regular function (not attached to any object), what does it refer to?

In non-strict mode (browser):

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

showThis(); // In browser: window object
Enter fullscreen mode Exit fullscreen mode

Here, the function is called by the global context (the window object in browsers), so this points to window.

In strict mode:

"use strict";
function showThis() {
  console.log(this);
}

showThis(); // undefined
Enter fullscreen mode Exit fullscreen mode

In strict mode, JavaScript doesn't default to the global object – it leaves this as undefined.

Remember: In regular functions, this depends on how the function is called, not where it's defined.

this Inside Objects (Methods)

When a function is a property of an object (called a method), this refers to that object.

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

person.greet(); // Hello, I'm Satya
Enter fullscreen mode Exit fullscreen mode

Here, greet is called on the person object, so this inside greet refers to person.

But what if we take the method out of the object?

const greetFn = person.greet;
greetFn(); // Hello, I'm undefined (or window.name in non-strict mode)
Enter fullscreen mode Exit fullscreen mode

Now greetFn is just a regular function, and this is no longer person. This is where we need help to fix this.

Why Do We Need call(), apply(), and bind()?

Sometimes we want to borrow a method from one object and use it for another. Or we want to make sure this points to the right object no matter how the function is called.

That's exactly what call, apply, and bind do – they let us explicitly set the value of this.

1. call() – Call a function with a given this and arguments

The call() method calls a function with a specified this value and arguments provided individually.

Syntax:

functionName.call(thisArg, arg1, arg2, ...)
Enter fullscreen mode Exit fullscreen mode

Example:

const person1 = { name: "Raj" };
const person2 = { name: "Priya" };

function introduce(city, country) {
  console.log(`${this.name} from ${city}, ${country}`);
}

introduce.call(person1, "Delhi", "India"); // Raj from Delhi, India
introduce.call(person2, "Mumbai", "India"); // Priya from Mumbai, India
Enter fullscreen mode Exit fullscreen mode

Real Life Example:

const car = {
  brand: "Toyota",
  getDetails: function(model) {
    console.log(`${this.brand} ${model}`);
  }
};

const anotherCar = { brand: "Honda" };

car.getDetails.call(anotherCar, "Civic"); // Honda Civic
Enter fullscreen mode Exit fullscreen mode

Here, car's method is called with this set to anotherCar. We borrowed the method!

2. apply() – Same as call, but arguments as an array

apply() is exactly like call(), but it takes arguments as an array (or array-like object).

Syntax:

functionName.apply(thisArg, [argsArray])
Enter fullscreen mode Exit fullscreen mode

Example:

const person1 = { name: "Raj" };
const person2 = { name: "Priya" };

function introduce(city, country) {
  console.log(`${this.name} from ${city}, ${country}`);
}

introduce.apply(person1, ["Delhi", "India"]); // Raj from Delhi, India
introduce.apply(person2, ["Mumbai", "India"]); // Priya from Mumbai, India
Enter fullscreen mode Exit fullscreen mode

When to use apply?

When your arguments are already in an array, or you need to pass a variable number of arguments.

const numbers = [10, 20, 30, 40];
console.log(Math.max.apply(null, numbers)); // 40
Enter fullscreen mode Exit fullscreen mode

(Here, this doesn't matter, so we pass null.)

3. bind() – Returns a new function with bound this

bind() does not call the function immediately. Instead, it creates a new function with this permanently set to the value you provide.

Syntax:

const boundFunction = functionName.bind(thisArg, arg1, arg2, ...)
Enter fullscreen mode Exit fullscreen mode

Example:

const person = { name: "Satya" };

function greet(greeting) {
  console.log(`${greeting}, I'm ${this.name}`);
}

const boundGreet = greet.bind(person, "Hello");
boundGreet(); // Hello, I'm Satya
Enter fullscreen mode Exit fullscreen mode

Real Life Example:

const user = {
  name: "Amit",
  sayHi: function() {
    console.log(`Hi, ${this.name}`);
  }
};

// Let's say we want to pass this method to a button click
const sayHiFn = user.sayHi.bind(user);

// Later, when sayHiFn is called, it still uses 'user' as this
sayHiFn(); // Hi, Amit
Enter fullscreen mode Exit fullscreen mode

Without bind, if we passed user.sayHi directly, this would become the button or global object.

Difference Between call, apply, and bind

Method When is function called? How arguments are passed Use case
call() Immediately Individually, separated by commas When you know the arguments and want to invoke right away
apply() Immediately As an array When arguments are in an array, or you have variable number of arguments
bind() Returns a new function (not called yet) Individually (pre-filled) When you need a function with a fixed this to be used later (e.g., event handlers, callbacks)

Simple way to remember:

  • call – C for Comma-separated arguments.
  • apply – A for Array of arguments.
  • bind – B for Borrow and Bind for later use.

Conclusion

  • this refers to who is calling the function.
  • In regular functions (non-method), this is the global object (or undefined in strict mode).
  • In methods, this is the object the method is called on.
  • call() and apply() immediately invoke the function with a specified this.
  • bind() returns a new function with this permanently set, ready to be called later.
  • Use call for comma-separated arguments, apply for array arguments, and bind when you need a function with a fixed context for future use.

Understanding this and these methods will save you from many bugs and give you superpowers in controlling function execution. Practice with the examples and soon it'll become second nature.


Hope you liked this blog. If there's any mistake or something I can improve, do tell me. You can find me on LinkedIn and X, I post more stuff there.

Top comments (0)