Understanding prototype.apply() in JavaScript

Abstract image used to represent Understanding prototype.apply() in JavaScript
Image by Steve Johnson.

In JavaScript, Function.prototype.apply() is a method which plays a crucial role in objectoriented, functional programming. This method allows for dynamic invocation of functions and provides flexibility in the way that arguments are passed to these functions.

Here, I intend to discuss this in detail, explore apply(), and describe how it is used in scenarios where it becomes particularly useful.


What is prototype.apply()?

Function.prototype.apply() is a method that calls a function with a given this value and arguments provided as an array (or an arraylike object). It is similar to Function.prototype.call(), but the way arguments are passed is different.

Syntax

func.apply(thisArg, argsArray)
  • func: The function to be called.
  • thisArg: The value of this provided for the call to func.
  • argsArray: An array or arraylike object whose elements become the arguments passed to func. Omit it, or pass null or undefined, to call the function without arguments.

Using apply() in JavaScript

A Basic Example

const greet = (subject) => {
  console.log(`Hello, ${subject}!`);
};

greet.apply(null, ['World']);  //=> "Hello, World!"

Admittedly it's a very basic example, but the distinction is useful: ["World"] is the argument list, so greet receives the string "World" as its first argument. If we already had an array called argsArray, we would pass it directly; [argsArray] would instead pass that whole array as one argument.

The null supplied as thisArg has no effect here because greet is an arrow function, which keeps its surrounding this binding.


Why and When to Use apply()

  • Dynamic Function Invocation

    : apply() is useful when the number of arguments to pass to the function is not known until runtime.
  • Working with Arraylike Objects

    : It's handy for functions that accept an array of arguments, especially when dealing with arraylike objects (like arguments in a function).
  • Borrowing Methods

    : apply() allows an object to use a method belonging to another object, which is a powerful feature for method borrowing.

A More In‑Depth Example

I tend to find that borrowing methods makes up a significant chunk of my personal use of apply(), so to offer a slightly more indepth example:

const person = {
  name: 'Maddie',
  introduce() {
    console.log(`Hello, my name is ${this.name}`);
  },
};

const anotherPerson = { name: 'Brian' };
person.introduce.apply(anotherPerson);  //=> "Hello, my name is Brian"

Here, anotherPerson borrows the introduce method from person using apply().


Differences from call()

Although .apply() is similar to call() (which you can read about in more detail here), the key difference is in how arguments are passed:

  • call() accepts an argument list.
  • apply() accepts a single array of arguments.

Everything else being equal (and we'll get to that in a minute), choosing between call() and apply() typically depends on the format in which arguments are available.


Use Cases in Modern JavaScript

Really, this article is a few years too late. With the spread operator (...) available in ES6, the necessity of apply() for spreading array arguments has gone. Now, you can now use call() with spread syntax to achieve essentially the same thing. However, apply() remains useful in cases where the arraylike object isn't a proper array, or if you're working with an older JavaScript codebase.


Wrapping Up

Function.prototype.apply() is a versatile method in JavaScript, which enables dynamic function invocation and method borrowing across different objects. Understanding apply() adds to your developer toolkit, especially in scenarios involving complex object manipulations or where arguments to a function are determined at runtime.


Untangling a delivery problem?

Send the symptoms, constraints, and affected routes. I'll help identify whether the issue sits in the application, platform, content model, deployment path, or search surface.