.call(..) and the
.apply(..) functions. Both of these functions have a similar purpose; the major difference lies in how you plan to pass parameters. If you remember from the last blog entry, we examined briefly the
.apply(..) function when we were creating a cross-browser solution for
In this entry, I want to focus more on the core purpose of these functions. This will eventually lead me into a future blog entry in which I talk about a solution for IE's lack of 'this' keyword support when using
But first we must understand more thoroughly what
.apply(..) allow us to do. Read on to learn more.
Given a reference to a function,
myFn, it is possible to invoke that function by calling:
At first glace, it doesn't seem like there is a whole lot to gain by doing this. After all, a simple call to
myFn(); will also invoke the function.
The real magic happens when you realize that you can manually specify which object you want the function to treat as the current object. Take the following example:
this.name = name;
this.color = color;
this.age = age;
function frog(name, age)
this.name = name;
this.color = 'green';
this.age = age;
var str =
this.constructor.name.toUpperCase() + '\n' +
'name: ' + this.name + '\n' +
'color: ' + this.color + '\n' +
'age: ' + this.age;
var c = new cat('fluffy', 'white', 3);
var f = new frog('igor', 2);
Here, we've defined two custom objects:
frog, as well as a function
showAnimal(..) (notice that the
showAnimal(..) function takes no parameters). Instead,
showAnimal(..) uses the
this keyword (which referes to the current object) to access various properties of the current object.
Now if you're anything like me, then the first time you took a look at this bit of code, your exact thought was proabably "… what?"
It's not that complicated really. Imagine if we had hooked up the
showAnimal(..) function inside of the
frog class like this:
// name, color, age assignments here
this.show = showAnimal;
this.show = showAnimal; essentially defines a public function of the cat class which is just a reference to the
showAnimal(..) function. Since this function is a member of the cat class, it has access to all of cat's internal member variables.
The issue here is that we'd have to hook up the
.show(..) function for both the
cat and the
frog class. And if we decided to create more animals that had the properties
name, color and
age, then we'd have to hook up the
.show(..) function for those classes as well.
Notice how our first code snippet alleviates the need to hook up the
showAnimal(..) function individually for each class. By invoking the
showAnimal(..) function via
animalRef as the current object (the object referred to by the
If you wanted to pass additional parameters to the
showAnimal(..) function, you could easily do that. Simply specify the paramaters you wish to pass in the same way you would any other function — only, do it after the first parameter, as in the following example:
saySomethingToCat.call(myCat, 'Hello there', 'How are you?');
function saySomethingToCat(msg1, msg2)
alert(msg1 + ' ' + this.name + '. ' + msg2);
In this example, we passed in 2 (additional) parameters to the function
saySomethingToCat(..). It's important to note that even those we're passing in 3 parameters (
'Hello there', and
'How are you?'), the first parameter,
myCat, doesn't really count becuase it is this object that will be treated as the current object (and hence, the one referred to by the
this keyword inside the
.apply(..) function works in almost exactly the same way, but with one minor difference (and if you read my last blog post, you probably already know what it is).
Instead of passing additional parameters as a comma delimited list as you would with the
.call(..) function, you simply pass an array containing the data you want wish to pass as parameters. This can be very useful if the data you want to pass is already in an array (as it was when we were dealing with the
arguments array in the last blog entry).
Rather than create a whole new example to demonstrate the
.apply(..) function, I'm simply going to refer you to my previous blog entry regarding cross-browser
As a final note, I like to say that I, personally, have found very few uses for the
.apply(..) functions. One example is obviously the
setTimeout(..) function in my last blog entry that I won't shut up about, and another is the ability to fix a
this keyword reference in IE (but that is another blog entry — hopefully coming soon).
That doesn't mean there aren't more uses. It's just that, for almost every example I've seen using
.apply(..), I can imagine other ways that I like better to accomplish the same thing. But if any readers out there have know of other useful way to take advantage of either of these functions, feel free to send me an email. I'd love to hear from you.
That about wraps up this entry. As always, comments welcome.