fn.apply() vs fn.call() in JavaScript + better alternative
Published on in JavaScript and Mnemonics
Last updated on
Mnemonic:
"a" (apply()) for an array,
"c" (call()) for commas.
But Reflect.apply() is better.
Table of contents
fn.apply() vs fn.call()
The
apply() method
takes arguments as an array,
and the
call() method
takes multiple arguments:
function foo() {}
const thisArg = {}
const args = [1, 2, 3]
foo.apply(thisArg, args)
foo.apply(thisArg, [1, 2, 3])
foo.call(thisArg, ...args)
foo.call(thisArg, 1, 2, 3)
Mnemonic:
- a (
apply()) for an array - c (
call()) for commas.
Source for the mnemonic: What is the difference between call and apply? on Stack Overflow.
The better alternative
Reflect.apply()
is better.
Like fn.apply(),
it takes arguments as an array:
function foo() {}
const thisArg = {}
const args = [1, 2, 3]
Reflect.apply(foo, thisArg, args)
Reflect.apply(foo, thisArg, [1, 2, 3])
It's "arguably less verbose and easier to understand" than fn.apply().
"In addition,
when you accept arbitrary methods,
it's not safe to assume .apply() exists or is not overridden."
Source:
Prefer Reflect.apply() over Function#apply() ESLint rule
from
eslint-plugin-unicorn.
A note about verbosity
This is not verbose:
foo.apply(thisArg, [1, 2, 3])
But it's not safe either as stated above.
This is safe but also verbose:
Function.prototype.apply.call(foo, thisArg, [1, 2, 3])
Now it's easy to see
why Reflect.apply() is "arguably less verbose and easier to understand":
Reflect.apply(foo, thisArg, [1, 2, 3])