Named parameters in JavaScript and ECMAScript 6

[2011-11-22] esnext, dev, javascript, jslang
(Ad, please don’t block)
Warning: This blog post is outdated. Instead, read section “Named parameters” in “JavaScript for impatient programmers”.
This post explains what named parameters are, how they can be simulated in JavaScript, and what improvements ECMAScript 6 will bring. Obviously, what is said about methods here applies to functions, as well.

Positional parameters and named parameters. When calling a method in a programming language, the actual parameters (specified by the caller) have to be mapped to the formal parameters (of a method definition). There are two common ways to do so:

  • Positional parameters are mapped by position: The first actual parameter is mapped to the first formal parameter etc.
  • Named parameters use names (labels) to perform the mapping. Names are associated with formal parameters in a method definition and label actual parameters in a method call. It does not matter in which order named parameters appear, as long as they are correctly labeled. The following sections explain why named parameters are useful and give examples.
Named parameters as descriptions. As soon as a method has more than one parameter, things can get confusing as to what each parameter is used for. For example, let’s say you have a type Entries that manages entries of some kind. Given an instance entries, you can make the following method invocation.
entries.select(3, 5);
What do these two numbers mean? Python supports named parameters and they make it easy to see what is going on:
entries.select(from=3, to=5)

Named parameters and options. The optional parameters of a method are sometimes called its options. Positional parameters are awkward if parameters can be omitted anywhere (not just at the end). Then any subset of the options can be active and one often has to insert blanks such as null for the inactive ones. Named parameters help with options in two ways: They clearly describe what parameters are active and they allow one to simply drop the inactive ones.

JavaScript. JavaScript does not have native support for named parameters like Python and many other languages. But there is a reasonably elegant simulation: provide optional parameters via an object literal. The result is a so-called options object that is assigned to a single formal parameter. Using this technique, an invocation of select() looks as follows:

entries.select({ from: 3, to: 5 });
The method receives an options object with the properties from and to. You can drop any of the options:
entries.select({ from: 3 });
entries.select({ to: 5 });
entries.select();
Obviously, you could also introduce positional parameters. It is customary for the options to come last, but JavaScript does not force you to do so.
entries.select(value1, value2, { from: 3, to: 5 });
Method select() would be implemented as follows in current JavaScript:
Entries.prototype.select = function (options) {
  if (options === undefined) options = {};
  if (options.from === undefined) options.from = 0;
  if (options.to === undefined) options.to = this.length;
  
  // Use options.from and options.to
};
Not particularly elegant. It can be shortened a little, but then you have to worry about what values JavaScript considers to be false:
Entries.prototype.select = function (options) {
  if (!options) options = {};
  if (!options.from) options.from = 0;
  if (!options.to) options.to = this.length;
  
  // Use options.from and options.to
};
EcmaScript 6. In ECMAScript 6 (ES6), we get a much more comfortable solution (reminder via Brendan Eich):
Entries.prototype.select = function (
  { from = 0, to = this.length }) {
  
  // Use `from` and `to`
};
Allen Wirfs-Brock points out that if you want people to be able to omit the options object then the above changes to:
Entries.prototype.select = function (
  { from = 0, to = this.length } = {}) {
  
  // Use `from` and `to`
};
JavaScript engines should be able to optimize invocations of functions and methods with ES6-style named parameters such that no temporary object is created.