jsguides

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

NameTypeRequiredDescription
targetfunctionyesThe function to call. Must be callable.
thisArgumentanyyesThe value bound as this inside target during the call. null and undefined are allowed.
argumentsListarray-likeyesAn 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() throws TypeError if target is not a function.
  • Reflect.apply() throws TypeError if argumentsList is null or undefined. This is the most important behavioural difference from Function.prototype.apply().
  • Reflect.apply() does not coerce thisArgument. A primitive stays a primitive; null stays null. 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+.

See also