JavaScript .apply and .call methods

In JavaScript every function/object has a .call() and .apply() method. Both these methods allow you to invoke a method where you override the this reference, essentially making it seem as if it was a method on another function/object;

The difference between the two methods is that .call() allows you to pass arguments for the method as parameters whereas .apply() lets you pass in arguments as an array.

function Person() {
    this.name = 'Julia';
}
Person.prototype.display = function display(age, title) {
    alert(this.name + ' ' + age + ' (' + title + ')');
}

var person = new Person();

var x = { name: 'Michael' };

person.display(23, 'Lawyer'); // Julia 23 (Lawyer)

person.display.call(x, 23, 'Lawyer'); // Michael 23 (Lawyer)

person.display.apply(x, [23, 'Lawyer']); // Michael 23 (Lawyer)

As you can see the .call() method takes an arbitrary number of parameters where .apply() takes exactly 2 parameters the second being an array of arguments. Both methods take as the first parameter what will be used as the this pointer for the duration of the invocation.

Let’s walk through the example above. When we invoke the method directly without using .call() or .apply() this refers to the object which the function was invoked on. However, when we use .call() or .apply() the first parameter allows us to override this pointer. this now refers to x for the entire method invocation. This result in both .apply and .call() displaying ‘Michael’ where normal method invocation displays ‘Julia’.

Using .apply() over .call()
Lets now look at an example to show why there exists both an .call() and .apply(), since it might not seem clear why we even need an .apply() method and are not simply content with the .call() method.

var person = { name: 'Michael' };

function easy()
{
	alert('Easy! ' + this.name + ' likes to ' + Array.prototype.join.call(arguments, ' '));
}
function epic()
{
	alert('Epic! ' + this.name + ' likes to ' + Array.prototype.join.call(arguments, ' '));
}

function dance(func) {
	if (arguments.length > 3)
		epic.apply(person, arguments);
	else
		easy.apply(person, arguments);
}

dance('move', 'twist', 'turn'); // Easy! Michael likes to move twist turn

dance('move', 'twist', 'turn', 'bump'); // Epic! Michael likes to move twist turn bump

In cases where we do not want to care about the number of arguments a function needs, .apply becomes the only game in town. In the example above we have a function dance that takes an arbitrary number or arguments as parameters. dance tests for the number of arguments then separates them into 2 groups depending on whether or not dance was called with more than 3 arguments. Depending on the result we then call either easy or epic but without actually knowing the number of arguments we are passing on. Finally both easy and epic access the arguments passed through the arguments object and displaying them independently of how many was passed.

Performance
Lastly it would seem that there is also a performance difference between the 2 methods. According to jsPerf.com .call() outperforms .apply(). As to why this is the case you will have to look elsewhere :) The test can be found here

I hope this post has helped you find clarity about the 2 methods in question. Please feel free to comment and ask questions below.

Speak Your Mind

*