What is the difference between call and apply?
What is the difference between using call and apply to invoke a function?
var func = function(){
alert('hello!');
};
func.apply();
vs
func.call();
Are there performance differences between the two methods? When is it best to use call over apply and vice versa?
Here's a small-ish post, I wrote on this:
http://sizeableidea.com/call-versus-apply-javascript/
var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };
function execute(arg1, arg2){
console.log(this.which, arg1, arg2);
}
//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope
//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope
//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"
Another example with Call, Apply and Bind. The difference between Call and Apply is evident, but Bind works like this:
- Bind returns an instance of a function that can be executed
- First Parameter is 'this'
- Second parameter is a Comma separated list of arguments (like Call)
}
function Person(name) {
this.name = name;
}
Person.prototype.getName = function(a,b) {
return this.name + " " + a + " " + b;
}
var reader = new Person('John Smith');
reader.getName = function() {
// Apply and Call executes the function and returns value
var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]); console.log("Apply " + baseName);
var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); console.log("Call " + baseName);
// Bind returns function which can be invoked
var baseName = Person.prototype.getName.bind(this, "is a", "boy"); console.log("Bind " + baseName());
return('Hello reader');
}
console.log(reader.getName());
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.
Difference between these to methods are, how you want to pass the parameters.
“A for array and C for comma” is a handy mnemonic.
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
// Output:
// My name is John and I am a fireman.
// My name is Susan and I am a school teacher.
// My name is Claude and I am a mathematician.
// My name is Matthew and I am a physicist.
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...)
Even though call
and apply
achive the same thing, I think there is atleast one place where you cannot use call
but can only use apply
. That is when you want to support inheritance and want to call the constructor.
Here is a function allows you to create classes which also supports creating classes by extending other classes.
function makeClass( properties ) {
var ctor = properties['constructor'] || function(){}
var Super = properties['extends'];
var Class = function () {
// Here 'call' cannot work, only 'apply' can!!!
if(Super)
Super.apply(this,arguments);
ctor.apply(this,arguments);
}
if(Super){
Class.prototype = Object.create( Super.prototype );
Class.prototype.constructor = Class;
}
Object.keys(properties).forEach( function(prop) {
if(prop!=='constructor' && prop!=='extends')
Class.prototype[prop] = properties[prop];
});
return Class;
}
//Usage
var Car = makeClass({
constructor: function(name){
this.name=name;
},
yourName: function() {
return this.name;
}
});
//We have a Car class now
var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat
var SuperCar = makeClass({
constructor: function(ignore,power){
this.power=power;
},
extends:Car,
yourPower: function() {
return this.power;
}
});
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6
It is useful at times for one object to borrow the function of another object, meaning that the borrowing object simply executes the lent function as if it were its own.
A small code example:
var friend = {
car: false,
lendCar: function ( canLend ){
this.car = canLend;
}
};
var me = {
car: false,
gotCar: function(){
return this.car === true;
}
};
console.log(me.gotCar()); // false
friend.lendCar.call(me, true);
console.log(me.gotCar()); // true
friend.lendCar.apply(me, [false]);
console.log(me.gotCar()); // false
These methods are very useful for giving objects temporary functionality.
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.
The main difference is using call we can change the scope and pass arguments as normal, but apply let you call the using arguments as an Array(pass them as array). but in term of what they to do in your code, they are pretty similar.
While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.
So as you see, there is not a big difference, but still there are cases we prefer using call() or apply(). For example look at the code below, which finding smallest and largest number in an array from MDN, using the apply method:
// min/max number in an array
var numbers = [5, 6, 2, 3, 7];
// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)
var min = Math.min.apply(null, numbers)
So the main difference is just the way we passing the argumenets:
Call:
function.call(thisArg, arg1, arg2, ...);
Apply:
function.apply(thisArg, [argsArray]);
Call() takes comma-separated arguments, ex:
.call(scope, arg1, arg2, arg3)
and apply() takes an array of arguments, ex:
.apply(scope, [arg1, arg2, arg3])
here are few more usage examples: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
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"]);
From the MDN docs on Function.prototype.apply() :
The apply() method calls a function with a given
this
value and arguments provided as an array (or an array-like object).Syntax
fun.apply(thisArg, [argsArray])
From the MDN docs on Function.prototype.call() :
The call() method calls a function with a given
this
value and arguments provided individually.Syntax
fun.call(thisArg[, arg1[, arg2[, ...]]])
From Function.apply and Function.call in JavaScript :
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.
Code example :
var doSomething = function() {
var arr = [];
for(i in arguments) {
if(typeof this[arguments[i]] !== 'undefined') {
arr.push(this[arguments[i]]);
}
}
return arr;
}
var output = function(position, obj) {
document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}
output(1, doSomething(
'one',
'two',
'two',
'one'
));
output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
'one',
'two',
'two',
'one'
]));
output(3, doSomething.call({one : 'Steven', two : 'Jane'},
'one',
'two',
'two',
'one'
));
See also this Fiddle.
I'd like to show an example, where the 'valueForThis' argument is used:
Array.prototype.push = function(element) {
/*
Native code*, that uses 'this'
this.put(element);
*/
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
**details: http://es5.github.io/#x15.4.4.7*
The difference is that call() takes the function arguments separately, and apply() takes the function arguments in an array.
Call and apply both are used to force the this
value when a function is executed. The only difference is that call
takes n+1
arguments where 1 is this
and 'n' arguments
. apply
takes only two arguments, one is this
the other is argument array.
The advantage I see in apply
over call
is that we can easily delegate a function call to other function without much effort;
function sayHello() {
console.log(this, arguments);
}
function hello() {
sayHello.apply(this, arguments);
}
var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');
Observe how easily we delegated hello
to sayHello
using apply
, but with call
this is very difficult to achieve.
Fundamental difference is that call()
accepts an argument list, while apply()
accepts a single array of arguments.
We can differentiate call and apply methods as below
CALL : A function with argument provide individually. If you know the arguments to be passed or there are no argument to pass you can use call.
APPLY : Call a function with argument provided as an array. You can use apply if you don't know how many argument are going to pass to the function.
There is a advantage of using apply over call, we don't need to change the number of argument only we can change a array that is passed.
There is not big difference in performance. But we can say call is bit faster as compare to apply because an array need to evaluate in apply method.
Follows an extract from Closure: The Definitive Guide by Michael Bolin. It might look a bit lengthy, but it's saturated with a lot of insight. From "Appendix B. Frequently Misunderstood JavaScript Concepts":
What
this
Refers to When a Function is CalledWhen calling a function of the form
foo.bar.baz()
, the objectfoo.bar
is referred to as the receiver. When the function is called, it is the receiver that is used as the value forthis
:If there is no explicit receiver when a function is called, then the global object becomes the receiver. As explained in "goog.global" on page 47, window is the global object when JavaScript is executed in a web browser. This leads to some surprising behavior:
Even though
obj.addValues
andf
refer to the same function, they behave differently when called because the value of the receiver is different in each call. For this reason, when calling a function that refers tothis
, it is important to ensure thatthis
will have the correct value when it is called. To be clear, ifthis
were not referenced in the function body, then the behavior off(20)
andobj.addValues(20)
would be the same.Because functions are first-class objects in JavaScript, they can have their own methods. All functions have the methods
call()
andapply()
which make it possible to redefine the receiver (i.e., the object thatthis
refers to) when calling the function. The method signatures are as follows:Note that the only difference between
call()
andapply()
is thatcall()
receives the function parameters as individual arguments, whereasapply()
receives them as a single array:The following calls are equivalent, as
f
andobj.addValues
refer to the same function:However, since neither
call()
norapply()
uses the value of its own receiver to substitute for the receiver argument when it is unspecified, the following will not work:The value of
this
can never benull
orundefined
when a function is called. Whennull
orundefined
is supplied as the receiver tocall()
orapply()
, the global object is used as the value for receiver instead. Therefore, the previous code has the same undesirable side effect of adding a property namedvalue
to the global object.It may be helpful to think of a function as having no knowledge of the variable to which it is assigned. This helps reinforce the idea that the value of this will be bound when the function is called rather than when it is defined.
End of extract.