.

Tags:

Handling a function with a variable number of arguments is always tricky in JavaScript. At least, we still have this arguments object which can be used to retrieve all arguments used to invoke a function. With the upcoming ECMAScript 6, no such hack is necessary anymore since we can start using its rest parameter feature.

To see how a rest parameter works, consider the following scenario. You drive a truck which delivers some supplies to a grocery store. As you unload the supplies, you add them to the store:

store.add('fruit', 'apple');
store.add('dairy', 'milk', 'cheese', 'yoghurt');
store.add('pastries', 'donuts', 'croissants');

whereby add is implemented as something like:

store.add = function(category) {
  var items = [].slice.call(arguments, 1);
  items.forEach(function (item) {
    store.aisle[category].push(item);
  });
};

Note how arguments object can’t be treated as a normal array, although it behaves almost like an array. A well-known trick with Array.prototype.slice and Function.prototype.call is the workaround, giving us the list of all arguments which comes after the first one (category).

With a rest parameter (Section 13.1, ES 6 draft Rev 13), the implementation is much simpler. It is even self-explanatory.

store.add = function(category, ...items) {
  items.forEach(function (item) {
    store.aisle[category].push(item);
  });
};

Another typical use-case where a rest parameter could be useful is a pubsub-like pattern. If you write a Backbone.js-based application, triggering an event via Backbone.Event.trigger is a common practice. Because an event may require one or more parameters, the implementation of the trigger function itself looks like:

trigger: function(name) {
    if (!this._events) return this;
    var args = slice.call(arguments, 1);
    /// ... do something with args ...
    return this;
},

for which I’m sure you can come up with a slightly different look if you have the rest parameter feature as your disposal!

Obviously we don’t need a rest parameter if we switch the API to accept an array as the second argument. However, in some cases, it would feel less natural. For example, a string formatter implementation is expected to follow the de-facto printf format string rather than grouping every parameters in a simple array.

Just like other syntactic sugar in ECMAScript 6, a rest parameter does not radically change you write your JavaScript code. It does however make the code more tool-friendly, shifting the semantic interpretation of the code from the run-time behavior into something at the syntax level. Once editors and IDEs understand the construct, a simple code hint which reveals the function signature is more than enough to indicate that the said function accepts a variable number of arguments.

Isn’t it exciting?

  • http://twitter.com/jefftschwartz Jeff Schwartz

    It makes for a nice addition to the language but why on earth did they chose to call it ‘rest’ parameters? While the use case and implementation are clear enough I think the name ‘rest’ isn’t. Weird, hey?

    • http://ariya.ofilabs.com/ Ariya Hidayat

      I think the terminology came from ActionScript.

      • Florian Margaine

        Or Scheme. Or Lisp.

    • http://twitter.com/mikesherov Mike Sherov

      It’s called rest, because its the rest of the parameters.

  • Brian Cray

    Would much rather see keyword parameters. This still forces an order to the parameters as far as I can tell.

  • http://twitter.com/brunolazzaro Bruno Lazzaro

    If i’m not mistaken you can also do

    store.add = function(category, …items) {
    store.aisle[category].push(…items);
    };
    And it would push each item into the array instead of inserting the array. It’s one of the good things about spreads :)

    Source: http://tc39wiki.calculist.org/es6/spread/

    • http://ariya.ofilabs.com/ Ariya Hidayat

      You just spoil the next-week installment of this ES6 series :)