Reflect.apply()
Reflect.apply(target, thisArgument, argumentsList) Description
Reflect.apply() calls a target function with an explicit this value and a list of arguments. It is the reflective counterpart to Function.prototype.apply(), introduced in ES2015 alongside the Reflect namespace object and Proxy.
You reach for Reflect.apply() when you want to invoke a function without writing a method call on the function itself, or when you are forwarding a call from inside a Proxy trap and want the standard, non-coercing semantics. The third argument must be an actual array or array-like object, which is the one place this method diverges from Function.prototype.apply() in a way that surprises people.
Syntax
Reflect.apply(target, thisArgument, argumentsList)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
target | function | yes | The function to call. Must be callable. |
thisArgument | any | yes | The value bound as this inside target during the call. null and undefined are allowed. |
argumentsList | array-like | yes | An array or array-like object whose elements are spread as positional arguments to target. Must be provided as an object; null and undefined throw. |
Return value
The value returned by target. If target throws, Reflect.apply() re-throws that exception unchanged. Thenables, promises, and plain values all pass through with no wrapping.
Examples
Call a function with an explicit this and arguments
console.log(Reflect.apply(Math.floor, undefined, [1.75]));
// 1
console.log(Reflect.apply(String.fromCharCode, undefined, [104, 105, 33]));
// "hi!"
Forward a call from a Proxy apply trap
The apply trap on a function proxy is the canonical place to see Reflect.apply() used. Forward the call rather than calling target.apply(thisArg, args), because Reflect preserves the original thisArgument exactly.
function greet(greeting, name) {
return `${greeting}, ${this.prefix} ${name}`;
}
const ctx = { prefix: 'Mr.' };
const wrapped = new Proxy(greet, {
apply(target, thisArg, args) {
return Reflect.apply(target, thisArg, args);
}
});
console.log(wrapped.call(ctx, 'Hello', 'Smith'));
// "Hello, Mr. Smith"
The argumentsList gotcha
Function.prototype.apply() tolerates a missing argument list and treats it as “no arguments”. Reflect.apply() does not, and that is the difference most worth remembering.
function noArgs() {
return 'called';
}
console.log(noArgs.apply(null)); // "called"
console.log(noArgs.apply(null, undefined)); // "called"
console.log(Reflect.apply(noArgs, null, [])); // "called"
console.log(Reflect.apply(noArgs, null)); // TypeError
console.log(Reflect.apply(noArgs, null, undefined)); // TypeError
If your argument list might be missing, decide deliberately: either pass [] explicitly, or fall back to a direct call. A silent zero-arg call is rarely what you want from code that thinks it has arguments ready.
Use an array-like as the argument list
argumentsList does not have to be a real Array. Any object with a length property and integer keys works, because Reflect uses CreateListFromArrayLike under the hood.
function sum(a, b, c) {
return a + b + c;
}
const arrayLike = { 0: 10, 1: 20, 2: 30, length: 3 };
console.log(Reflect.apply(sum, null, arrayLike));
// 60
Construct a class with Reflect.apply()
When target is a class constructor, Reflect.apply() invokes it through the [[Construct]] slot, the same internal slot new uses. You get construction semantics even though you are not writing new.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
const args = [3, 4];
const p = Reflect.apply(Point, null, args);
console.log(p);
// Point { x: 3, y: 4 }
This is handy when you have an array of constructor arguments and a class reference, and you want to avoid new target(...args) for some reason (logging, dispatch, conditional construction). Plain functions called this way run as ordinary calls.
Notes
Reflect.apply()throwsTypeErroriftargetis not a function.Reflect.apply()throwsTypeErrorifargumentsListisnullorundefined. This is the most important behavioural difference fromFunction.prototype.apply().Reflect.apply()does not coercethisArgument. A primitive stays a primitive;nullstaysnull.Function.prototype.apply()boxes primitives into wrapper objects in non-strict mode, which is one reason Proxy handlers reach for Reflect instead.- The return value passes through unchanged, including thenables and promises. There is no wrapping or unwrapping.
Reflect.apply()was added in ES2015 and is available in every current browser engine and in Node.js 6+.