Real-Life Use Cases for call, apply, and bind

The concept behind call, apply or bind boils down to explicitly setting function parameters, including the this context. These techniques become handy when the usual ways of defining function parameters are insufficient.

apply

You'll probably never need apply nowadays because the spread operator (...) has taken over its common use case. Previously, if you had parameters in an array, you'd use apply:

const nums = [1, 2, 3];
const largest = Math.max.apply(null, nums);
console.log(largest); // 3

But now, the spread operator makes it simpler:

const nums = [1, 2, 3];
const largest = Math.max(...nums);
console.log(largest); // 3

call

call works like calling a function, but with the this context moved to the first parameter:

const nums = [1, 2, 3];

console.log(nums.includes(2)); // true
console.log(Array.prototype.includes.call(nums, 2)); // true

This is rarely useful but can come in handy when you need to call one object's method on a different object.

const calculator = {
  add: function (x, y) {
    return x + y;
  },
};

const user = {
  name: "John",
  age: 28,
  // Using the add function from the calculator object
  calculate: function (a, b) {
    console.log(
      `${this.name} says the sum is: ${calculator.add.call(this, a, b)}`
    );
  },
};

// Using the calculate method of the user object
user.calculate(5, 7);

bind

Bind is the most useful among the three. It allows you to pass parameters to a function before calling it, essentially creating a new function with those parameters baked in:

const nums = [1, 2, 3];
const numsIncludesThree = Array.prototype.includes.bind(nums, 3);

console.log(numsIncludesThree()); // true
nums.pop();
console.log(numsIncludesThree()); // false

This is great for building up functions with predefined parameters and introducing concepts like partially applying functions, factory functions, and currying.

Binding in Class Definitions

Binding in class definitions, like using bind in the constructor, used to be common:

class User {
  constructor(name) {
    this.name = name;
    this.greet = this.greet.bind(this);
  }

  greet() {
    console.log(`Hello, ${this.name}!`);
  }
}

This lets you use a method from your class in situations where the expected context (this) might not be set properly. For instance, when using it as a callback for things like event listeners or setTimeout.

const user = new User("Sue");
setTimeout(user.greet, 1000); // Hello, Sue!

However, this approach has fallen out of fashion. People don't use classes as frequently, and there are simpler ways to achieve the same behavior, like using arrow functions.

setTimeout(() => {
  user.greet();
}, 1000);

// Hello, Sue! (no bind required)

In conclusion, you might not use call or apply often, but bind (or arrow functions) is quite handy, especially when dealing with event handlers or callbacks. It helps in creating functions with predefined parameters and ensures that the function context is maintained.

Learn Higher-Order Functions

Write code that is easier to understand and maintain.

You've heard about higher-order functions, but every explanation you've come across is either too technical or too vague. You're searching for something clear and practical, with examples that will help you practice and truly master the concept.

Higher-order functions are key to writing better code, essential for your projects, and expected in interviews. But getting started can be tough.

But what if you could? What if you had access to easy-to-understand content that not only explains higher-order functions but also provides hands-on practice? You’d finally feel confident using them in your projects, knowing exactly what they do and how to leverage them effectively.

It’s true, finding the right resources to learn higher-order functions can be challenging… but it doesn’t have to be.

Get my guide, where you’ll:

  • Understand why higher-order functions are worth learning and how they can transform your approach to writing JavaScript.
  • Gain clarity as I break down higher-order functions into simple, everyday language.
  • Master three important higher-order functions: map, filter, and reduce, with plenty of examples to solidify your understanding.
  • Apply your knowledge with real-world examples that demonstrate how these concepts work together, so you can use them easily in your projects or write better code in your interviews.

Get the Guide