Using call and apply in Javascript

A few steps than the road of their development as a developer, most people dipping their toes into the Javascript waters will run into call() and apply().

Function.prototype.call() and Function.prototype.apply(), that is. Their functionality isn’t that hard to understand – you use both methods to call a function with a given this value and some arguments to go with the function.

Example:

function person(number) {
    console.log(number, this);
}

person(1);
person.apply(['Apply'], [2]);
person.call(['Call'], 3);

If you run that in your console it will give you 1, *Window*, 2, ["Apply"], 3, ["Call"] back.

The example will also give you a hint about the differences between call() and apply() – it’s all about how you pass in the additional arguments. With call you pass them in as a list of arguments and with apply you pass them in as an array. So call(this, 1, 2, 3) is equvialent to apply(this, [1, 2, 3]). Since ECMAScript 5 the arguments array in apply can even be an array-like object instead of a proper array, which is super useful if you just want to pass on an arguments object from another function.

I guess that the difference is kind of subtle and that it leaves it up to personal preference which one you use. I personally use apply() almost exclusively and if you have ES5 support I would recommend you doing so do to reap the benefits of the arguments object.

That’s it for the differences between the two methods. Still not sure how to use them? Here’s a contrived example:

function Laptop(name, price) {
    this.name = name;
    this.price = price;
    console.log(this)

    return this;
}

function Apple(name, price) {
    // Laptop.apply(this, arguments); // Instead of Laptop(name, price);
    this.brand = 'Apple';
}
Apple.prototype = new Laptop();

function Asus(name, price) {
    Laptop.apply(this, arguments); // Instead of Laptop(name, price)
    this.brand = 'Asus';
}
Asus.prototype = new Laptop();

var macbook = new Apple('Macbook', 1000);
var vivo = new Asus('VivoBook', 700);

What we have here is a case of chained constructors. The mother constructor, Laptop(), sets up the whole chain by defining price and name of a certain laptop. Apple() and Asus() inherit from Laptop() but also add their own property, brand.

If we would have used an ordinary function call, Laptop(price, name) in Apple or Asus this would actually have pointed to the window object and neither name nor price would have been set on the subcategories of laptops. But when we use apply() and pass in the subfunction itself as this into Laptop(), hence setting the price and name on that very function.

Simple, beatiful and efficient – when you know how to use it! Do you ever use apply() or call() and do you prefer either of them?