ECMAScript.next: TC39’s July 2012 meeting

[2012-08-03] esnext, tc39, dev, javascript
(Ad, please don’t block)
TC39 (Technical Committee 39) works on the upcoming ECMAScript.next [1] standard. They have several meetings per year and in July, there was another one. This blog post summarizes the most important decisions. It is based on the following minutes by Rick Waldron:

Introduction

In this post, I have omitted all decisions that concern minor details or that it is better to learn about later, once the relevant parts of the language are finished. The arguably biggest decision was to accept classes for ECMAScript.next. Consult [2] for details. The following sections cover the remaining decisions. Let me know if there is something that you think should be mentioned here.

Quasi literals are now called template strings

Quasi literals are now called template strings. Which is a better and more descriptive name. Several other minor details have changed: The curly braces after a dollar sign ($) are now mandatory and the data structure that is passed to a handler has been simplified. You can read the details at [3].

Tail calls

Further progress to specify tail calls has been made, their inclusion in ECMAScript.next seems likely. The last function call in a function is called a tail call [4]. The data of the current function can be completely removed from the stack before making such a call, because it does not need to return to its place of invocation. This kind of optimization is popular in functional programming languages: Recursion is common and tail calls reduce the risk of a stack overflow. Therefore, more functional programming techniques become feasible in JavaScript and it will be more appealing as a compilation target for functional languages.

Unicode support

Work continues to bring full Unicode support to JavaScript. Unicode represents characters as code points, numbers between 0 and 0x0010FFFF. You need to serialize code points if you want to store them in a file, send them over a network, etc. To do so, they are encoded as code units. A code unit encoding scheme is measured by the minimum number of bits that is needed to represent a code point. For example, UTF-8 has 8 bit code units and JavaScript internally uses 16 bit code units. The problem is that several parts of JavaScript interpret characters as 16 bit code points. In order to represent code points beyond 16 bits (as needed by many Asian languages), several parts of the specification have to be changed. One alternative was to simply switch to 32 bit characters, but that breaks existing code that uses strings to store binary data. Hence, UTF-16 encoding beyond 16 bits will be supported for the source code, strings and regular expressions. Examples for new mechanisms that are introduced to do so:
  • A character escape with curly braces allows one to specify an arbitrary code point, which is represented as either one or two UTF-16 code units.
        "<<some emoji>>" === "\u{1F601}" === "\uD83D\uDE01"
    
    Escapes without braces are always a single UTF-16 code unit.
  • Regular expressions can have a /u flag that enables a Unicode mode with features such as curly-brace character escapes.
  • Iterating over the code points in a string – which are sometimes one 16 bit character long, sometimes two characters. Two APIs are under consideration:
    • String.fromCodePoint: build a string from integer values.
    • String.prototype.codePointAt: retrieve the n-th code point in a string.

Parameter default values

If a parameter has a default value, what should happen if someone passes undefined as a parameter? Quoting Waldron, the following is a function whose parameter newLevel has the default value 0.
    function setLevel(newLevel = 0) {
        ...
    }
For the call setLevel(), newLevel should obviously be 0, but what about setLevel(undefined)? A decision has been made to use the default value here, too. The reason is that that allows a function that calls setLevel to pass on a value denoting “missing parameter” that triggers the default value. Hence, if there are several functions that invoke setLevel, the default only needs to be defined once, instead of redundantly in each invoking function. Let’s look at several examples.

Forwarding an option to a parameter

The first example is a function setOptions that calls setLevel.
   function setOptions(options) {
       setLevel(options.dimmerLevel);  // missing property => undefined
       setMotorSpeed(options.speed);
       ...
    }
    setOptions({ speed: 5 });
setOptions does not have to know setLevel’s default, it can trigger it via undefined. If that isn’t what you want, you can fill in missing properties via a function such as _.defaults().

Forwarding a parameter to a parameter

Brendan Eich gives another example of why undefined should trigger the default value. A function inc that calls a function add and passes on the positional parameter opt_y.
    function add(x = 0, y = 0) {
        return x + y;
    }
    function inc(opt_y) {
        return add(1, opt_y);
    }
If opt_y is omitted, add should use the default value for the second parameter.

Forwarding an option to an option

Eich also mentions a versions of add and inc that use options [5]:
    function add({x = 0, y = 0}) {
        return x + y;
    }
    function inc({opt_y}) {
        return add({x:1, y:opt_y});
    }
The problem is the same, only now opt_y and y are nested inside an object.

References

  1. ECMAScript: ES.next versus ES 6 versus ES Harmony
  2. ECMAScript.next: classes
  3. Quasi-literals: embedded DSLs in ECMAScript.next
  4. Asynchronous programming and continuation-passing style in JavaScript
  5. Keyword parameters in JavaScript and ECMAScript.next