Skip to main content

Function.prototype.apply

Function.prototype.apply calls a function with an explicitly specified context (this), passing the arguments to it as an array. It is the close sibling of the call method, and the only difference between them is the way arguments are passed.

Theory

TL;DR

  • apply invokes the function immediately and lets you set this manually.
  • Arguments are passed as an array or an array-like object, not as a comma separated list.
  • call does the same thing, but its arguments are listed one by one.
  • bind invokes nothing: it only returns a new function with a bound this.
  • Classic uses: Math.max.apply(null, nums) and borrowing array methods for arguments.
  • The modern replacement in many cases is the spread syntax, func(...args).

Quick example

javascript
function sum(a, b, c) { return a + b + c; } const numbers = [1, 2, 3]; // the arguments are already in an array, so apply fits perfectly console.log(sum.apply(null, numbers)); // 6

Syntax

javascript
func.apply(thisArg, [argsArray])
  • thisArg is the object that becomes this inside the function;
  • argsArray is an array (or an array-like object) of arguments.

Basic use with an explicit context:

javascript
function greet(city, job) { console.log(`I am ${this.name} from ${city}, working as a ${job}`); } const user = { name: 'Maria' }; greet.apply(user, ['Kyiv', 'Frontend developer']); // I am Maria from Kyiv, working as a Frontend developer

The same thing via call:

javascript
greet.call(user, 'Kyiv', 'Frontend developer');

The difference is only in how the arguments are passed:

  • call -> comma separated,
  • apply -> as an array.

Working with array-like objects

apply is often used when the arguments are already stored in an array or a similar structure (arguments, NodeList and so on). That makes it possible to borrow an array method for an object that has no array methods of its own:

javascript
function logArgs() { console.log(arguments); // turn arguments into an array with Array.prototype.slice const arr = Array.prototype.slice.apply(arguments); console.log(arr); } logArgs(1, 2, 3, 4); // arguments -> [1, 2, 3, 4]

Here apply lets you call an array method (slice) on the arguments object, which is not an array but does have length and numeric indices.

Math.max and Math.min via apply

Math.max and Math.min do not accept an array, only a list of numbers. apply solves this elegantly:

javascript
const nums = [10, 20, 5, 40]; console.log(Math.max.apply(null, nums)); // 40 console.log(Math.min.apply(null, nums)); // 5

The ES6 equivalent:

javascript
Math.max(...nums); // modern spread syntax

apply vs call and bind

MethodWhat it doesHow arguments are passedWhen it runs
callCalls the function with the given thisComma separatedImmediately
applyCalls the function with the given thisAs an arrayImmediately
bindCreates a new function with a bound thisComma separatedLater (when called)

Summary of apply:

PropertyDescription
PurposeCall a function with a given this
Argument passingAn array or an array-like object
Execution contextGlobal or set manually
When to use itWhen the arguments are already collected in an array
Modern alternativefunc(...args) (spread syntax)

Details of thisArg

If thisArg is null or undefined, then:

  • in strict mode ('use strict') -> this = undefined;
  • in sloppy mode -> this = window (or global in Node.js).
javascript
function showThis() { console.log(this); } showThis.apply(null); // window (in sloppy mode)

That is exactly why examples such as Math.max.apply(null, nums) safely pass null first: those functions do not need a context at all.

Common mistakes

  • Mixing up call and apply. apply expects one array, so sum.apply(null, 1, 2, 3) will not work, while sum.call(null, [1, 2, 3]) passes the array as the first argument.
  • Assuming apply returns a new function. That is what bind does; apply executes the function right away and returns its result.
  • Counting on a global this in strict mode. Modules and classes run in strict mode, so with null the this stays undefined.
  • Passing a very large array into apply. Every element becomes a separate argument, so with arrays of hundreds of thousands of items you can hit RangeError: Maximum call stack size exceeded.
  • Trying to construct an object with apply. apply does not work with new: to call a constructor with an array of arguments you need Reflect.construct(Ctor, args) or new Ctor(...args).

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.