Function.prototype.apply
Introduction
Function.prototype.apply invokes a function immediately with a specific this value and an array-like list of arguments: fn.apply(thisArg, argsArray).
It is the sibling of call. Use call when arguments are already separate; use apply when arguments are already collected.
Why This Matters
apply appears in legacy JavaScript, polyfills, function forwarding, and many interview implementations. Even though spread syntax replaced some common uses, apply remains essential for understanding how bind and function delegation work.
Theory
Syntax
fn.apply(thisArg, argsArray)
apply does two things:
- Invokes
fnimmediately. - Expands
argsArrayinto positional arguments while bindingthistothisArgfor regular functions.
call vs apply
| Tool | Argument style | Timing |
|---|---|---|
call | fn.call(obj, a, b) | Immediate |
apply | fn.apply(obj, [a, b]) | Immediate |
bind | fn.bind(obj, a) | Later |
Forwarding arguments
apply is especially useful when writing wrappers. If a wrapper receives an array of values and needs to forward them to another function, apply avoids manually indexing each one.
Modern spread comparison
fn.apply(obj, args) is similar to fn.call(obj, ...args), but apply works directly with array-like values in older code. Modern code often uses spread for arrays, but interviews still ask apply because it reveals explicit binding mechanics.
Arrow caveat
Like call, apply cannot change an arrow function's lexical this.
Visual Diagrams
calculate.apply(invoice, [2, 5, 1])
| | |
| | +-- array-like arguments
| +----------- thisArg
+------------------- function to invoke now
Inside calculate:
this === invoice
first arg === 2
second arg === 5
third arg === 1`apply` is explicit binding plus argument-list expansion.
Code Examples
Forward a collected argument list
Wrappers often receive arguments as an array and forward them with apply.
Legacy maximum with apply
Before spread syntax, apply was the common way to pass an array to a variadic function.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function multiply(a, b) {2 console.log(this.factor * a * b);3}4 5const context = { factor: 3 };6multiply.apply(context, [2, 5]);Predict the output #2
1function joinThree(a, b, c) {2 console.log(this.prefix + a + b + c);3}4 5joinThree.apply({ prefix: 'id-' }, [1, 2, 3]);Coding Exercises
Implement an argument-forwarding wrapper
MediumImplement withReceiver(fn, receiver) so it returns a function that accepts an array of arguments and invokes fn with receiver as this. Use apply.
Interview Questions
1What is the difference between `call` and `apply`?
Both invoke a function immediately with an explicit this value. call takes arguments one by one: fn.call(obj, a, b). apply takes a single array-like argument list: fn.apply(obj, [a, b]).
2When is `apply` useful in modern JavaScript?
It is useful for forwarding a collected argument list, writing wrappers, maintaining legacy code, and understanding polyfills such as simplified bind. Modern spread syntax covers many array use cases, but apply is still the explicit-binding primitive for array-like forwarding.
Quiz
1. Which expression calls `fn` with `obj` as `this` and `[1, 2]` as the argument list?
2. What is the timing difference between `apply` and `bind`?
Summary
- `apply` invokes a function immediately with explicit `this`.
- The second argument to `apply` is an array-like list of arguments.
- `apply` is ideal for forwarding collected arguments.
- Modern spread replaces some uses but not the underlying concept.
- Arrow functions ignore `apply` for `this` binding.
Cheat Sheet
Syntax: fn.apply(thisArg, argsArray).
Timing: immediate invocation.
Arguments: collected array-like list.
Use cases: wrappers, argument forwarding, legacy variadic calls.
Compare: call takes separate args; bind returns a later function.