Understanding call, apply, and bind in JavaScript

Hero image for Understanding call, apply, and bind in JavaScript. Image by Lewis Kang'ethe Ngugi.
Hero image for 'Understanding call, apply, and bind in JavaScript.' Image by Lewis Kang'ethe Ngugi.

JavaScript's this keyword often confuses frontend developers, especially when working with functions. Understanding how to control the value of this will make your life as a frontend developer much easier for you and your colleagues: it will allow you to write cleaner and more predictable code.

That's where call, apply, and bind come in. These methods provide us with powerful tools for setting the this context. In this article, I intend to explore what these methods are, how they differ, and when you should use each one. By the end, you'll hopefully have a decent grasp of how to leverage them effectively within your projects.


What Are call, apply, and bind?

At their core, call, apply, and bind are all methods available on every JavaScript function. They allow you to explicitly set the value of this when invoking a function, which gives us control over its execution context.

call

The call method invokes a function with a specified this value and arguments provided one by one. For example:

function greet(greeting, name) {  console.log(`${greeting}, ${name}! My context is:`, this);}greet.call({ role: 'developer' }, 'Hello', 'Maddie');// Output: Hello, Maddie! My context is: { role: 'developer' }

apply

The apply method is similar to call, but it expects arguments in the form of an array:

const numbers = [5, 10, 15];const max = Math.max.apply(null, numbers);console.log(max);  // Output: 15

bind

The bind method is a little different, it doesn't execute the function immediately. Instead, it returns a new function with the specified this value permanently bound to it:

const user = { name: 'Sophie' };function introduce() {  console.log(`My name is ${this.name}`);}const boundIntroduce = introduce.bind(user);boundIntroduce();  // Output: My name is Sophie

All three of these methods are particularly useful when you need to explicitly define the this context, such as borrowing methods from other objects, working with callbacks, or ensuring consistent context in asynchronous functions.


What is call in JavaScript?

The call method is a builtin JavaScript function available on all functions. It allows us to invoke a function whilst explicitly specifying the value of this. This can be incredibly useful when borrowing methods from other objects or when you need granular control over a function's context.

Syntax of call

functionName.call(thisArg, arg1, arg2, ...);
  • thisArg: The value you want to use as the this context for the function.
  • arg1, arg2, ...: Additional arguments passed to the function.

Using call to Borrow Methods

One of the most common use cases for call is borrowing methods from elsewhere in the codebase. For example, if you want to use an array method on a different type of object, you could use call to make it work:

const person = {  firstName: 'John',  lastName: 'Doe',  fullName: function () {    return `${this.firstName} ${this.lastName}`;  },};const anotherPerson = { firstName: 'Jane', lastName: 'Smith' };// Borrowing fullName method for anotherPersonconsole.log(person.fullName.call(anotherPerson));  // Output: "Jane Smith"

Passing Arguments with call

We can also pass arguments directly to the function that we're calling:

function greet(greeting, punctuation) {  console.log(`${greeting}, ${this.name}${punctuation}`);}const user = { name: 'Ellie' };// Invoking greet with a custom `this` and argumentsgreet.call(user, 'Hello', '!');  // Output: "Hello, Ellie!"

Key Considerations

  • If thisArg is null or undefined, the default this will be the global object (window in browsers, global in Node.js). In strict mode, this will be undefined.
  • Unlike apply, which we'll discuss in a minute, call requires individual arguments to be passed, not an array.

What is apply in JavaScript?

The apply method is fairly similar to call in that it allows you to invoke a function whilst explicitly specifying the value of this. However, apply differs in how it handles additional arguments. Instead of passing them individually, apply expects an arraylike object as the second argument.

Syntax of apply

functionName.apply(thisArg, [arg1, arg2, ...]);
  • thisArg: The value to use as this inside the function.
  • [arg1, arg2, ...]: An array or arraylike object containing arguments for the function.

Using apply to Borrow Methods

Just like with call, apply is useful for borrowing methods. The key difference is that apply simplifies scenarios where arguments are already in an array or arraylike object. For example:

const numbers = [5, 10, 15, 20];const maxNumber = Math.max.apply(null, numbers);console.log(maxNumber);  // Output: 20

In this example, apply makes it easy to pass the array of numbers to Math.max.

Example with apply

Here's another quick and practical example:

function introduce(greeting, punctuation) {  console.log(`${greeting}, my name is ${this.name}${punctuation}`);}const person = { name: 'Ellie' };const args = ['Hello', '!'];introduce.apply(person, args);  // Output: "Hello, my name is Ellie!"

Key Considerations

  • As with call, if thisArg is null or undefined, the function will default to the global object (or undefined in strict mode).
  • Use apply when arguments are already in an array or need to be dynamically constructed.

What is bind in JavaScript?

Compared to call and apply, the bind method is relatively unique. Instead of immediately invoking the function, bind returns a new function with this permanently set to the value we specify. This can be especially useful for creating function references with a fixed context.

Syntax of bind

const boundFunction = functionName.bind(thisArg, arg1, arg2, ...);
  • thisArg: The value to use as this inside the new function.
  • arg1, arg2, ...: Optional arguments that are preset when the function is called.

Using bind for Function Context

Here's a quick example:

const user = {  name: 'Maddie',  greet: function () {    console.log(`Hello, ${this.name}!`);  },};const greetUser = user.greet.bind(user);// Even if `greetUser` is called in a different context, `this` is preservedgreetUser();  // Output: "Hello, Maddie!"

Presetting Arguments with bind

We using bind, it is also possible to preset arguments, like this:

function multiply(a, b) {  return a * b;}const double = multiply.bind(null, 2);  // `a` is pre-set to 2console.log(double(5));  // Output: 10

In this example, the bind method is used to create a new function, double, where the first argument of the multiply function (a) is permanently set to 2. When double is invoked with a single argument (5), it effectively calls multiply(2, 5) and returns the result, 10.

Here, we're demonstrating how bind can preset certain arguments, making it a powerful tool for creating specialized versions of functions tailored to specific needs or contexts.

Key Considerations

  • bind is ideal for event handlers or callbacks where preserving this is important.
  • The returned function from bind can still accept additional arguments beyond those preset.

When to Use call, apply, and bind

Understanding when to use each method is key to leveraging their strengths effectively. Here's a breakdown of typical use cases for each:

call

Use call when you need to immediately invoke a function with a specific this context and explicitly list the arguments. It's great for scenarios where you know the arguments in advance, such as when borrowing methods or performing inline function invocations.

For example, borrowing a method from another object:

const person = {  name: 'John',};function introduce(age) {  console.log(`Hi, I'm ${this.name} and I'm ${age} years old.`);}introduce.call(person, 30);// Output: Hi, I'm John and I'm 30 years old.

apply

Use apply when you need to immediately invoke a function, in much the same way as with call, but the arguments are already in an array or an arraylike structure. This is especially useful in scenarios where the arguments are dynamically generated or come from another function.

For example, finding the maximum value in an array:

const numbers = [5, 1, 7, 3];const maxNumber = Math.max.apply(null, numbers);console.log(maxNumber);  // Output: 7

bind

Use bind when you want to create a new function with a specific this context or preset arguments, but delay its execution. It is perfect for event handlers, callbacks, or scenarios where you need to reuse the function in different contexts.

For example, customising a function for repeated use:

const printer = {  prefix: 'Message:',};function printMessage(message) {  console.log(`${this.prefix} ${message}`);}const boundPrinter = printMessage.bind(printer);boundPrinter('Hello, World!');// Output: Message: Hello, World!

Wrapping up

The call, apply, and bind methods play crucial roles in JavaScript, offering developers powerful tools to control the this context within functions. Whether you're invoking a function immediately with dynamic arguments, working with arrays of arguments, or creating reusable functions with preset contexts, these methods ensure flexibility and clarity within your code.

Key Takeaways

  • call: Invokes a function immediately, with arguments provided individually.
  • apply: Similar to call, but expects arguments as an array, making it particularly useful for scenarios like using the Math methods.
  • bind: Creates a new function with a permanently bound this value, useful for event handlers and partial application.
  • These methods are essential for managing this dynamically and writing more maintainable code.
  • Understanding when and where to use each method is a key skill for any JavaScript developer.

In JavaScript, the ability to control the this context dynamically is invaluable, and call, apply, and bind provide the flexibility to do so effectively. With these tools in your arsenal, you'll be better equipped to handle complex coding challenges and write more adaptable, efficient code.


Categories:

  1. Development
  2. Front‑End Development
  3. Guides
  4. JavaScript