What is the difference between call and apply?
Solution 1
The difference is that apply
lets you invoke the function with arguments
as an array; call
requires the parameters be listed explicitly. A useful mnemonic is "A for array and C for comma."
See MDN's documentation on apply and call.
Pseudo syntax:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
There is also, as of ES6, the possibility to spread
the array for use with the call
function, you can see the compatibilities here.
Sample code:
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
Solution 2
K. Scott Allen has a nice writeup on the matter.
Basically, they differ on how they handle function arguments.
The apply() method is identical to call(), except apply() requires an array as the second parameter. The array represents the arguments for the target method."
So:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
Solution 3
To answer the part about when to use each function, use apply
if you don't know the number of arguments you will be passing, or if they are already in an array or array-like object (like the arguments
object to forward your own arguments. Use call
otherwise, since there's no need to wrap the arguments in an array.
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];
while (...) {
args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments
When I'm not passing any arguments (like your example), I prefer call
since I'm calling the function. apply
would imply you are applying the function to the (non-existent) arguments.
There shouldn't be any performance differences, except maybe if you use apply
and wrap the arguments in an array (e.g. f.apply(thisObject, [a, b, c])
instead of f.call(thisObject, a, b, c)
). I haven't tested it, so there could be differences, but it would be very browser specific. It's likely that call
is faster if you don't already have the arguments in an array and apply
is faster if you do.
Solution 4
Here's a good mnemonic. Apply uses Arrays and Always takes one or two Arguments. When you use Call you have to Count the number of arguments.
Solution 5
While this is an old topic, I just wanted to point out that .call is slightly faster than .apply. I can't tell you exactly why.
See jsPerf, http://jsperf.com/test-call-vs-apply/3
[UPDATE!
]
Douglas Crockford mentions briefly the difference between the two, which may help explain the performance difference... http://youtu.be/ya4UHuXNygM?t=15m52s
Apply takes an array of arguments, while Call takes zero or more individual parameters! Ah hah!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
Noob
Currently a Ruby/Rails developer at Shopify, have also done javascript, Java and .Net programming in past lives.
Updated on July 08, 2022Comments
-
Noob almost 2 years
What is the difference between using
Function.prototype.apply()
andFunction.prototype.call()
to invoke a function?var func = function() { alert('hello!'); };
func.apply();
vsfunc.call();
Are there performance differences between the two aforementioned methods? When is it best to use
call
overapply
and vice versa?-
Larry Battle about 12 yearsThink of
a
in apply for array of args andc
in call for columns of args. -
Samih over 10 years@LarryBattle I do almost the same, but I think a in apply for array and c in call for comma (i.e comma separated arguments).
-
Ringo over 10 yearsI agree it's stupid. What's annoying is that somehow this question gets asked during interviews because some influential chump added the question to their list of important js questions.
-
neaumusic over 9 yearsthe default "arguments" array that gets passed into a function's scope gets passed on with apply. arguments goes with array goes with apply, call accepts a manual list of models, not a collection object (array)
-
Gras Double over 9 yearsYou apply for a job once (one argument), you [phone] call people many times (several arguments). Alternative: there are [too?] many Call of Duty games.
-
Gras Double over 9 yearsMore classic, there's only one array, you apply it [as a whole], there're several arguments, you call them [in a row]. Take your pick :)
-
Gajus over 9 yearsWhen the intention is to invoke a variadic function with a list of argument values regardless of "this" value, then use the ES6 spread operator, e.g.
fn(...input)
where input is an array. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… -
DevWL over 8 yearsIf you use "apply" or "call" only to chenge the "this" reference, and the function you refer to will not take any arguments, there is no diference what so ever.
-
Ankit Singh over 7 yearsIn ES6, if you've got an array of arguments
args
, only difference would be of three dots...
. ie:fn.apply(context, args)
orfn.call(context, ...args)
-
-
devios1 about 13 yearsAre they both supported by the majority of browsers? I seem to remember reading that
call()
was more of an IE thing. -
angry kiwi almost 13 yearsthe second parameter of apply() and call() is optional, not required.
-
Eric Hodonsky over 12 yearsThis depends on what the function does with the parameters/array, if it doesn't need to process the array, does it take less time?
-
Josh Mc about 12 yearsInterestingly even without the array, call is still much faster. jsperf.com/applyvscallvsfn2
-
Kevin Schroeder almost 12 yearsOne thing to add is that the args must be a numerical array ([]). Associative arrays ({}) will not work.
-
Martijn over 11 years@KevinSchroeder: In javascript parlance,
[]
is called an array,{}
is called an object. -
Ikrom about 11 yearsFirst parameter is not required too.
-
aziz punjani over 10 yearsI often used to forget which takes an array, and which expects you to list the arguments. A technique I used to remember it is if the first letter of the method starts with a then it takes an array i.e a pply array
-
Vincent McNabb over 10 years@JoshMc That would be very browser specific. In IE 11, I'm getting apply going twice as fast as call.
-
dantheta over 10 yearsUseful mnemonic right there!. I will change the 'one or two Arguments' to say 'a maximum of two Arguments' since neither the first or the second parameters of
apply
is required. I'm not sure though why one will callapply
orcall
without a parameter. Looks like someone is trying to find out why here stackoverflow.com/questions/15903782/… -
Raja over 10 years1. Creating a new array means the garbage collector will need to clean it up at some point. 2. Accessing items in the array using dereference is less efficient than accessing a variable (parameter) directly. (I believe that is what kmatheny meant by "parsing", which is actually something quite different.) But neither of my arguments explain the jsperf. That must be related to the engine's implementation of the two functions, e.g. perhaps they create an empty array anyway, if none was passed.
-
Mark Karwowski over 10 yearshere is another one: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply but basically it is right: .call(scope, arg1, arg2, arg3)
-
Michel Ayres over 10 yearsTo people that want to know how to see
console.log
check out: What is console.log and how do I use it? -
Faraz Kelhini over 10 years
-
some almost 10 years@SAM Using call instead of a normal function call only makes sense if you need to change the value of this for the function call. An example (that convert a functions arguments-object to an array):
Array.prototype.slice.call(arguments)
or[].slice.call(arguments)
. apply makes sense if you have the arguments in an array, for example in a function that calls another function with (almost) the same parameters. Recommendation Use a normal function callfuncname(arg1)
if that does what you need, and save call and apply for those special occasions when you really need them. -
Ralph Cowling over 9 years
theFunction.call(undefined, ["Claude", "mathematician"]); // 'My name is Claude,mathematician and I am a undefined.'
Oh Claude! <3 (photos-5.dropbox.com/t/1/…) -
Kunal Singh almost 9 yearstheFunction.apply(undefined, ["Susan", "school teacher"]); theFunction.call(undefined, "Claude", "mathematician"); Why the first argument is undefined while calling?
-
Kyll almost 9 yearsWhat does this answer provide that is not already well-provided in other answers?
-
Viktor Stolbin over 8 yearsJust to note the fact, that
additionalValues
is not referenced insideobj.addValues
body -
A J Qarshi over 8 years@KunalSingh Both
call
andapply
takes two parameters. The first argument ofapply' and
call` function must be the owner object and the second parameter will be array or comma separated parameters respectively. If you passnull
orundefined
as first argument then in non-strict mode they are replaced with global object i.e.window
-
xgqfrms over 7 years# codes bugs
theFunction.apply(undefined, ...["Matthew", "physicist"]);
A_better_apply -
xgqfrms over 7 years` // call() === comma-separated arguments (arguments-list) .call(this, args1, args2, args3, ...) // apply() === array of arguments (array-items) .apply(this, [arr0, arr1, arr2, ...]) `
-
Álvaro González about 7 yearsThe mnemonic alone is worth the answer. I don't think I'll need to look it up again!
-
Gary almost 7 yearsThank you for sharing the test and video
-
jhliberty over 6 yearsI believe call would work there with the spread operator as described in the selected answer. Unless I'm missing something.
-
jhliberty over 6 yearsI know you were answering the question but would like to add: you could have used bind when defining f.
var f = obj.addValues;
becomesvar f = obj.addValues.bind(obj)
and now f(20) would work without having to use call or apply every time. -
candy_man over 6 years@AJQarshi @KunalSingh Just to expound on Qarshi's answer, the first argument, owner object, as he called it, is the execution context you want to pass to the function(
this
context). When an object is passed as argument, then the function invoked is bound to the object's execution context and any reference to members in the function will indeed point to existing object members. Hope this makes sense. -
iamcastelli over 4 years@Ikrom, the first parameter is not required for
call
but a requirement forapply
-
Fralcon over 4 yearsI know you didn't write it, but you did highlight the text and examples from the book as relevant, and I am very grateful. They were very helpful.
-
Jakub Kubista about 4 yearsYou can hear this in every second interview, but I've seen this like once-twice in practice since most of the junior devs don't know this so it would lead just to misunderstandings.
-
Vega about 4 yearsAlthough we appreciate the effort you did making images, they are not very useful. Nobody can copy the code to use, test, improve... The code should be pasted as text here