Mozilla

JavaScript Articles

Sort by:

View:

  1. ES6 In Depth: Collections

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    Earlier this week, the ES6 specification, officially titled ECMA-262, 6th Edition, ECMAScript 2015 Language Specification, cleared the final hurdle and was approved as an Ecma standard. Congratulations to TC39 and everyone who contributed. ES6 is in the books!

    Even better news: it will not be six more years before the next update. The standard committee now aims to produce a new edition roughly every 12 months. Proposals for the 7th Edition are already in development.

    It is appropriate, then, to celebrate this occasion by talking about something I’ve been eager to see in JS for a long time—and which I think still has some room for future improvement!

    Hard cases for coevolution

    JS isn’t quite like other programming languages, and sometimes this influences the evolution of the language in surprising ways.

    ES6 modules are a good example. Other languages have module systems. Racket has a great one. Python too. When the standard committee decided to add modules to ES6, why didn’t they just copy an existing system?

    JS is different, because it runs in web browsers. I/O can take a long time. Therefore JS needs a module system that can support loading code asynchronously. It can’t afford to serially search for modules in multiple directories, either. Copying existing systems was no good. The ES6 module system would need to do some new things.

    How this influenced the final design is an interesting story. But we’re not here to talk about modules.

    This post is about what the ES6 standard calls “keyed collections”: Set, Map, WeakSet, and WeakMap. These features are, in most respects, just like the hash tables in other languages. But the standard committee made some interesting tradeoffs along the way, because JS is different.

    Why collections?

    Anyone familiar with JS knows that there’s already something like a hash table built into the language: objects.

    A plain Object, after all, is pretty much nothing but an open-ended collection of key-value pairs. You can get, set, and delete properties, iterate over them—all the things a hash table can do. So why add a new feature at all?

    Well, many programs do use plain objects to store key-value pairs, and for programs where this works well, there is no particular reason to switch to Map or Set. Still, there are some well-known issues with using objects this way:

    • Objects being used as lookup tables can’t also have methods, without some risk of collision.

    • Therefore programs must either use Object.create(null) (rather than plain {}) or exercise care to avoid misinterpreting builtin methods (like Object.prototype.toString) as data.

    • Property keys are always strings (or, in ES6, symbols). Objects can’t be keys.

    • There’s no efficient way to ask how many properties an object has.

    ES6 adds a new concern: plain objects are not iterable, so they will not cooperate with the forof loop, the ... operator, and so on.

    Again, there are plenty of programs where none of that really matters, and a plain object will continue to be the right choice. Map and Set are for the other cases.

    Because they are designed to avoid collisions between user data and builtin methods, the ES6 collections do not expose their data as properties. This means that expressions like obj.key or obj[key] cannot be used to access hash table data. You’ll have to write map.get(key). Also, hash table entries, unlike properties, are not inherited via the prototype chain.

    The upside is that, unlike plain Objects, Map and Set do have methods, and more methods can be added, either in the standard or in your own subclasses, without conflict.

    Set

    A Set is a collection of values. It’s mutable, so your program can add and remove values as it goes. So far, this is just like an array. But there are as many differences between sets and arrays as there are similarities.

    First, unlike an array, a set never contains the same value twice. If you try to add a value to a set that’s already in there, nothing happens.

    > var desserts = new Set("🍪🍦🍧🍩");
    > desserts.size
        4
    > desserts.add("🍪");
        Set [ "🍪", "🍦", "🍧", "🍩" ]
    > desserts.size
        4
    

    This example uses strings, but a Set can contain any type of JS value. Just as with strings, adding the same object or number more than once has no added effect.

    Second, a Set keeps its data organized to make one particular operation fast: membership testing.

    > // Check whether "zythum" is a word.
    > arrayOfWords.indexOf("zythum") !== -1  // slow
        true
    > setOfWords.has("zythum")               // fast
        true
    

    What you don’t get with a Set is indexing:

    > arrayOfWords[15000]
        "anapanapa"
    > setOfWords[15000]   // sets don't support indexing
        undefined
    

    Here are all the operations on sets:

    • new Set creates a new, empty set.

    • new Set(iterable) makes a new set and fills it with data from any iterable value.

    • set.size gets the number of values in the set.

    • set.has(value) returns true if the set contains the given value.

    • set.add(value) adds a value to the set. If the value was already in the set, nothing happens.

    • set.delete(value) removes a value from the set. If the value wasn’t in the set, nothing happens. Both .add() and .delete() return the set object itself, so you can chain them.

    • set[Symbol.iterator]() returns a new iterator over the values in the set. You won’t normally call this directly, but this method is what makes sets iterable. It means you can write for (v of set) {...} and so on.

    • set.forEach(f) is easiest to explain with code. It’s like shorthand for:

      for (let value of set)
          f(value, value, set);
      

      This method is analogous to the .forEach() method on arrays.

    • set.clear() removes all values from the set.

    • set.keys(), set.values(), and set.entries() return various iterators. These are provided for compatibility with Map, so we’ll talk about them below.

    Of all these features, the constructor new Set(iterable) stands out as a powerhouse, because it operates at the level of whole data structures. You can use it to convert an array to a set, eliminating duplicate values with a single line of code. Or, pass it a generator: it will run the generator to completion and collect the yielded values into a set. This constructor is also how you copy an existing Set.

    I promised last week to complain about the new collections in ES6. I’ll start here. As nice as Set is, there are some missing methods that would make nice additions to a future standard:

    • Functional helpers that are already present on arrays, like .map(), .filter(), .some(), and .every().

    • Non-mutating set1.union(set2) and set1.intersection(set2).

    • Methods that can operate on many values at once: set.addAll(iterable), set.removeAll(iterable), and set.hasAll(iterable).

    The good news is that all of these can be implemented efficiently using the methods provided by ES6.

    Map

    A Map is a collection of key-value pairs. Here’s what Map can do:

    • new Map returns a new, empty map.

    • new Map(pairs) creates a new map and fills it with data from an existing collection of [key, value] pairs. pairs can be an existing Map object, an array of two-element arrays, a generator that yields two-element arrays, etc.

    • map.size gets the number of entries in the map.

    • map.has(key) tests whether a key is present (like key in obj).

    • map.get(key) gets the value associated with a key, or undefined if there is no such entry (like obj[key]).

    • map.set(key, value) adds an entry to the map associating key with value, overwriting any existing entry with the same key (like obj[key] = value).

    • map.delete(key) deletes an entry (like delete obj[key]).

    • map.clear() removes all entries from the map.

    • map[Symbol.iterator]() returns an iterator over the entries in the map. The iterator represents each entry as a new [key, value] array.

    • map.forEach(f) works like this:

      for (let [key, value] of map)
        f(value, key, map);
      

      The odd argument order is, again, by analogy to Array.prototype.forEach().

    • map.keys() returns an iterator over all the keys in the map.

    • map.values() returns an iterator over all the values in the map.

    • map.entries() returns an iterator over all the entries in the map, just like map[Symbol.iterator](). In fact, it’s just another name for the same method.

    What is there to complain about? Here are some features not present in ES6 that I think would be useful:

    • A facility for default values, like Python’s collections.defaultdict.

    • A helper function, Map.fromObject(obj), to make it easy to write maps using object-literal syntax.

    Again, these features are easy to add.

    OK. Remember how I started this article with a bit about how unique concerns about running in the browser affect the design of JS language features? This is where we start to talk about that. I’ve got three examples. Here are the first two.

    JS is different, part 1: Hash tables without hash codes?

    There’s one useful feature that the ES6 collection classes do not support at all, as far as I can tell.

    Suppose we have a Set of URL objects.

    var urls = new Set;
    urls.add(new URL(location.href));  // two URL objects.
    urls.add(new URL(location.href));  // are they the same?
    alert(urls.size);  // 2
    

    These two URLs really ought to be considered equal. They have all the same fields. But in JavaScript, these two objects are distinct, and there is no way to overload the language’s notion of equality.

    Other languages support this. In Java, Python, and Ruby, individual classes can overload equality. In many Scheme implementations, individual hash tables can be created that use different equality relations. C++ supports both.

    However, all of these mechanisms require users to implement custom hashing functions and all expose the system’s default hashing function. The committee chose not to expose hash codes in JS—at least, not yet—due to open questions about interoperability and security, concerns that are not as pressing in other languages.

    JS is different, part 2: Surprise! Predictability!

    You would think that deterministic behavior from a computer could hardly be surprising. But people are often surprised when I tell them that Map and Set iteration visits entries in the order they were inserted into the collection. It’s deterministic.

    We’re used to certain aspects of hash tables being arbitrary. We’ve learned to accept it. But there are good reasons to try to avoid arbitrariness. As I wrote in 2012:

    • There is evidence that some programmers find arbitrary iteration order surprising or confusing at first. [1][2][3][4][5][6]
    • Property enumeration order is unspecified in ECMAScript, yet all the major implementations have been forced to converge on insertion order, for compatibility with the Web as it is. There is, therefore, some concern that if TC39 does not specify a deterministic iteration order, “the web will just go and specify it for us”.[7]
    • Hash table iteration order can expose some bits of object hash codes. This imposes some astonishing security concerns on the hashing function implementer. For example, an object’s address must not be recoverable from the exposed bits of its hash code. (Revealing object addresses to untrusted ECMAScript code, while not exploitable by itself, would be a bad security bug on the Web.)

    When all this was being discussed back in February 2012, I argued in favor of arbitrary iteration order. Then I set out to show by experiment that keeping track insertion order would make a hash table too slow. I wrote a handful of C++ microbenchmarks. The results surprised me.

    And that’s how we ended up with hash tables that track insertion order in JS!

    Strong reasons to use weak collections

    Last week, we discussed an example involving a JS animation library. We wanted to store a boolean flag for every DOM object, like this:

    if (element.isMoving) {
      smoothAnimations(element);
    }
    element.isMoving = true;
    

    Unfortunately, setting an expando property on a DOM object like this is a bad idea, for reasons discussed in the original post.

    That post showed how to solve this problem using symbols. But couldn’t we do the same thing using a Set? It might look like this:

    if (movingSet.has(element)) {
      smoothAnimations(element);
    }
    movingSet.add(element);
    

    There is only one drawback: Map and Set objects keep a strong reference to every key and value they contain. This means that if a DOM element is removed from the document and dropped, garbage collection can’t recover that memory until that element is removed from movingSet as well. Libraries typically have mixed success, at best, in imposing complex clean-up-after-yourself requirements on their users. So this could lead to memory leaks.

    ES6 offers a surprising fix for this. Make movingSet a WeakSet rather than a Set. Memory leak solved!

    This means it is possible to solve this particular problem using either a weak collection or symbols. Which is better? A full discussion of the tradeoffs would, unfortunately, make this post a little too long. If you can use a single symbol across the whole lifetime of the web page, that’s probably fine. If you end up wanting many short-lived symbols, that’s a danger sign: consider using WeakMaps instead to avoid leaking memory.

    WeakMap and WeakSet

    WeakMap and WeakSet are specified to behave exactly like Map and Set, but with a few restrictions:

    • WeakMap supports only new, .has(), .get(), .set(), and .delete().

    • WeakSet supports only new, .has(), .add(), and .delete().

    • The values stored in a WeakSet and the keys stored in a WeakMap must be objects.

    Note that neither type of weak collection is iterable. You can’t get entries out of a weak collection except by asking for them specifically, passing in the key you’re interested in.

    These carefully crafted restrictions enable the garbage collector to collect dead objects out of live weak collections. The effect is similar to what you could get with weak references or weak-keyed dictionaries, but ES6 weak collections get the memory management benefits without exposing the fact that GC happened to scripts.

    JS is different, part 3: Hiding GC nondeterminism

    Behind the scenes, the weak collections are implemented as ephemeron tables.

    In short, a WeakSet does not keep a strong reference to the objects it contains. When an object in a WeakSet is collected, it is simply removed from the WeakSet. WeakMap is similar. It does not keep a strong reference to any of its keys. If a key is alive, the associated value is alive.

    Why accept these restrictions? Why not just add weak references to JS?

    Again, the standard committee has been very reluctant to expose nondeterministic behavior to scripts. Poor cross-browser compatibility is the bane of Web development. Weak references expose implementation details of the underlying garbage collector—the very definition of platform-specific arbitrary behavior. Of course applications shouldn’t depend on platform-specific details, but weak references also make it very hard to know just how much you’re depending on the GC behavior in the browser you’re currently testing. They’re hard to reason about.

    By contrast, the ES6 weak collections have a more limited feature set, but that feature set is rock solid. The fact that a key or value has been collected is never observable, so applications can’t end up depending on it, even by accident.

    This is one case where a Web-specific concern has led to a surprising design decision that makes JS a better language.

    When can I use collections in my code?

    All four collection classes are currently shipping in Firefox, Chrome, Microsoft Edge, and Safari. To support older browsers, use a polyfill, like es6-collections.

    WeakMap was first implemented in Firefox by Andreas Gal, who went on to a stint as Mozilla’s CTO. Tom Schuster implemented WeakSet. I implemented Map and Set. Thanks to Tooru Fujisawa for contributing several patches in this area.

    Next week, ES6 In Depth starts a two-week summer break. This series has covered a lot of ground, but some of ES6’s most powerful features are yet to come. So please join us when we return with new content on July 9.

  2. ES6 In Depth: Using ES6 today with Babel and Broccoli

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    ES6 is here, and people are already talking about ES7, what the future holds, and what shiny features a new standard can offer. As web developers, we wonder how we can make use of it all. More than once, in previous ES6 In Depth posts, we’ve encouraged you to start coding in ES6, with a little help from some interesting tools. We’ve teased you with the possibility:

    If you’d like to use this new syntax on the Web, you can use Babel or Google’s Traceur to translate your ES6 code to web-friendly ES5.

    Today we’re going to show you step-by-step how it is done. The above-mentioned tools are called transpilers. A transpiler is also known as a source-to-source compiler—a compiler that translates between programming languages operating at comparable levels of abstraction. Transpilers let us write code using ES6 while also guaranteeing that we’ll be able to execute the code in every browser.

    Transpilation our salvation

    A transpiler is very easy to use. You can describe what it does in only two steps:

    1. We write code with ES6 syntax.

    let q = 99;
    let myVariable = `${q} bottles of beer on the wall, ${q} bottles of beer.`;
    

    2. We use the code above as input for the transpiler, which will process it and produce the following output:

    "use strict";
    
    var q = 99;
    var myVariable = "" + q + " bottles of beer on the wall, " + q + " bottles of beer."
    

    This is the good old JavaScript we know. It can be used in any browser.

    The internals of how a transpiler goes from input to output are highly complex and fall out of scope for this article. Just as we can drive a car without knowing all the internal engine mechanics, today we’ll leave the transpiler as a black box that is able to process our code.

    Babel in action

    There are a couple of different ways to use Babel in a project. There is a command line tool, which you can use with commands of the form:

    babel script.js --out-file script-compiled.js
    

    A browser-ready version is also available. You can include Babel as a regular JS library and then you can place your ES6 code in script tags with the type "text/babel".

    <script src="node_modules/babel-core/browser.js"></script>
    <script type="text/babel">
    // Your ES6 code
    </script>
    

    These methods do not scale when your code base starts to grow and you start splitting everything into multiple files and folders. At that moment, you’ll need a build tool and a way to integrate Babel with a build pipeline.

    In the following sections, we’ll integrate Babel into a build tool, Broccoli.js, and we’ll write and execute our first lines of ES6 through a couple of examples. In case you run into trouble, you can review the complete source code here: broccoli-babel-examples. Inside the repository you’ll find three sample projects:

    1. es6-fruits
    2. es6-website
    3. es6-modules

    Each one builds on the previous example. We start with the bare minimum and progress to a general solution, which can be used as the starting point of an ambitious project. In this post, we’ll cover the first two examples in detail. After we are done, you’ll be able to read and understand the code in the third example on your own.

    If you are thinking —I’ll just wait for browsers to support the new features— you’ll be left behind. Full compliance, if it ever happens, will take a long time. Transpilers are here to stay; new ECMAScript standards are planned to be released yearly. So, we’ll continue to see new standards released more often than uniform browser platforms. Hop in now and take advantage of the new features.

    Our first Broccoli & Babel project

    Broccoli is a tool designed to build projects as quickly as possible. You can uglify and minify files, among many other things, through the use of Broccoli plugins. It saves us the burden of handling files, directories, and executing commands each time we introduce changes to a project. Think of it as:

    Comparable to the Rails asset pipeline in scope, though it runs on Node and is backend-agnostic.

    Project setup

    Node

    As you might have guessed, you’ll have to install Node 0.11 or later.

    If you are in a unix system, avoid installing from the package manager (apt, yum). That is to avoid using root privileges during installation. It’s best to manually install the binaries, provided at the previous link, with your current user. You can read why using root is not recommended in Do not sudo npm. In there you’ll find other installation alternatives.

    Broccoli

    We’ll set up our Broccoli project first with:

    mkdir es6-fruits
    cd es6-fruits
    npm init
    # Create an empty file called Brocfile.js
    touch Brocfile.js
    

    Now we install broccoli and broccoli-cli

    # the broccoli library
    npm install --save-dev broccoli
    # command line tool
    npm install -g broccoli-cli
    

    Write some ES6

    We’ll create a src folder and inside we’ll put a fruits.js file.

    mkdir src
    vim src/fruits.js
    

    In our new file we’ll write a small script using ES6 syntax.

    let fruits = [
      {id: 100, name: 'strawberry'},
      {id: 101, name: 'grapefruit'},
      {id: 102, name: 'plum'}
    ];
    
    for (let fruit of fruits) {
      let message = `ID: ${fruit.id} Name: ${fruit.name}`;
    
      console.log(message);
    }
    
    console.log(`List total: ${fruits.length}`);
    

    The code sample above makes use of three ES6 features:

    1. let for local scope declarations (to be discussed in an upcoming blog post)
    2. for-of loops
    3. template strings

    Save the file and try to execute it.

    node src/fruits.js
    

    It won’t work yet, but we are about to make it executable by Node and any browser.

    let fruits = [
        ^^^^^^
    SyntaxError: Unexpected identifier
    

    Transpilation time

    Now we’ll use Broccoli to load our code and push it through Babel. We’ll edit the file Brocfile.js and add this code to it:

    // import the babel plugin
    var babel = require('broccoli-babel-transpiler');
    
    // grab the source and transpile it in 1 step
    fruits = babel('src'); // src/*.js
    
    module.exports = fruits;
    

    Notice that we require broccoli-babel-transpiler, a Broccoli plugin that wraps around the Babel library, so we must install it with:

    npm install --save-dev broccoli-babel-transpiler
    

    Now we can build our project and execute our script with:

    broccoli build dist # compile
    node dist/fruits.js # execute ES5
    

    The output should look like this:

    ID: 100 Name: strawberry
    ID: 101 Name: grapefruit
    ID: 102 Name: plum
    List total: 3
    

    That was easy! You can open dist/fruits.js to see what the transpiled code looks like. A nice feature of the Babel transpiler is that it produces readable code.

    Writing ES6 code for a website

    For our second example we’ll take it up a notch. First, exit the es6-fruits folder and create a new directory es6-website using the steps listed under Project setup above.

    In the src folder we’ll create three files:

    src/index.html

    <!DOCTYPE html>
    <html>
      <head>
        <title>ES6 Today</title>
      </head>
      <style>
        body {
          border: 2px solid #9a9a9a;
          border-radius: 10px;
          padding: 6px;
          font-family: monospace;
          text-align: center;
        }
        .color {
          padding: 1rem;
          color: #fff;
        }
      </style>
      <body>
        <h1>ES6 Today</h1>
        <div id="info"></div>
        <hr>
        <div id="content"></div>
    
        <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
        <script src="js/my-app.js"></script>
      </body>
    </html>
    

    src/print-info.js

    function printInfo() {
      $('#info')
      .append('<p>minimal website example with' +
              'Broccoli and Babel</p>');
    }
    
    $(printInfo);
    

    src/print-colors.js

    // ES6 Generator
    function* hexRange(start, stop, step) {
      for (var i = start; i < stop; i += step) {
        yield i;
      }
    }
    
    function printColors() {
      var content$ = $('#content');
    
      // contrived example
      for ( var hex of hexRange(900, 999, 10) ) {
        var newDiv = $('<div>')
          .attr('class', 'color')
          .css({ 'background-color': `#${hex}` })
          .append(`hex code: #${hex}`);
        content$.append(newDiv);
      }
    }
    
    $(printColors);
    

    You might have noticed this bit: function* hexRange — yes, that’s an ES6 generator. This feature is not currently supported in all browsers. To be able to use it, we’ll need a polyfill. Babel provides this and we’ll put it to use very soon.

    The next step is to merge all the JS files and use them within a website. The hardest part is writing our Brocfile. This time we install 4 plugins:

    npm install --save-dev broccoli-babel-transpiler
    npm install --save-dev broccoli-funnel
    npm install --save-dev broccoli-concat
    npm install --save-dev broccoli-merge-trees
    

    Let’s put them to use:

    // Babel transpiler
    var babel = require('broccoli-babel-transpiler');
    // filter trees (subsets of files)
    var funnel = require('broccoli-funnel');
    // concatenate trees
    var concat = require('broccoli-concat');
    // merge trees
    var mergeTrees = require('broccoli-merge-trees');
    
    // Transpile the source files
    var appJs = babel('src');
    
    // Grab the polyfill file provided by the Babel library
    var babelPath = require.resolve('broccoli-babel-transpiler');
    babelPath = babelPath.replace(/\/index.js$/, '');
    babelPath += '/node_modules/babel-core';
    var browserPolyfill = funnel(babelPath, {
      files: ['browser-polyfill.js']
    });
    
    // Add the Babel polyfill to the tree of transpiled files
    appJs = mergeTrees([browserPolyfill, appJs]);
    
    // Concatenate all the JS files into a single file
    appJs = concat(appJs, {
      // we specify a concatenation order
      inputFiles: ['browser-polyfill.js', '**/*.js'],
      outputFile: '/js/my-app.js'
    });
    
    // Grab the index file
    var index = funnel('src', {files: ['index.html']});
    
    // Grab all our trees and
    // export them as a single and final tree
    module.exports = mergeTrees([index, appJs]);
    

    Time to build and execute our code.

    broccoli build dist
    

    This time you should see the following structure in the dist folder:

    $> tree dist/
    dist/
    ├── index.html
    └── js
        └── my-app.js
    

    That is a static website you can serve with any server to verify that the code is working. For instance:

    cd dist/
    python -m SimpleHTTPServer
    # visit http://localhost:8000/
    

    You should see this:

    simple ES6 website

    More fun with Babel and Broccoli

    The second example above gives an idea of how much we can accomplish with Babel. It might be enough to keep you going for a while. If you want to do more with ES6, Babel, and Broccoli, you should check out this repository: broccoli-babel-boilerplate. It is also a Broccoli+Babel setup, that takes it up at least two notches. This boilerplate handles modules, imports, and unit testing.

    You can try an example of that configuration in action here: es6-modules. All the magic is in the Brocfile and it’s very similar to what we have done already.


    As you can see, Babel and Broccoli really do make it quite practical to use ES6 features in web sites right now. Thanks to Gastón I. Silva for contributing this week’s post!

    Next week, ES6 In Depth starts a two-week summer break. This series has covered a lot of ground, but some of ES6’s most powerful features are yet to come. So please join us when we return with new content on July 9.

    Jason Orendorff

    ES6 In Depth Editor

  3. ES6 In Depth: Symbols

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    What are ES6 symbols?

    Symbols are not logos.

    They’re not little pictures you can use in your code.

    let 😻 = 😺 × 😍;  // SyntaxError
    

    They’re not a literary device that stands for something else.

    They’re definitely not the same thing as cymbals.

    (It is not a good idea to use cymbals in programming. They have a tendency to crash.)

    So, what are symbols?

    The seventh type

    Since JavaScript was first standardized in 1997, there have been six types. Until ES6, every value in a JS program fell into one of these categories.

    • Undefined
    • Null
    • Boolean
    • Number
    • String
    • Object

    Each type is a set of values. The first five sets are all finite. There are, of course, only two Boolean values, true and false, and they aren’t making new ones. There are rather more Number and String values. The standard says there are 18,437,736,874,454,810,627 different Numbers (including NaN, the Number whose name is short for “Not a Number”). That’s nothing compared to the number of different possible Strings, which I think is (2144,115,188,075,855,872 − 1) ÷ 65,535 …though I may have miscounted.

    The set of Object values, however, is open-ended. Each object is a unique, precious snowflake. Every time you open a Web page, a rush of new objects is created.

    ES6 symbols are values, but they’re not strings. They’re not objects. They’re something new: a seventh type of value.

    Let’s talk about a scenario where they might come in handy.

    One simple little boolean

    Sometimes it would be awfully convenient to stash some extra data on a JavaScript object that really belongs to someone else.

    For example, suppose you’re writing a JS library that uses CSS transitions to make DOM elements zip around on the screen. You’ve noticed that trying to apply multiple CSS transitions to a single div at the same time doesn’t work. It causes ugly, discontinuous “jumps”. You think you can fix this, but first you need a way to find out if a given element is already moving.

    How can you solve this?

    One way is to use CSS APIs to ask the browser if the element is moving. But that sounds like overkill. Your library should already know the element is moving; it’s the code that set it moving in the first place!

    What you really want is a way to keep track of which elements are moving. You could keep an array of all moving elements. Each time your library is called upon to animate an element, you can search the array to see if that element is already there.

    Hmm. A linear search will be slow if the array is big.

    What you really want to do is just set a flag on the element:

    if (element.isMoving) {
      smoothAnimations(element);
    }
    element.isMoving = true;
    

    There are some potential problems with this too. They all relate to the fact that your code isn’t the only code using the DOM.

    1. Other code using for-in or Object.keys() may stumble over the property you created.

    2. Some other clever library author may have thought of this technique first, and your library would interact badly with that existing library.

    3. Some other clever library author may think of it in the future, and your library would interact badly with that future library.

    4. The standard committee may decide to add an .isMoving() method to all elements. Then you’re really hosed!

    Of course you can address the last three problems by choosing a string so tedious or so silly that nobody else would ever name anything that:

    if (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {
      smoothAnimations(element);
    }
    element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;
    

    This seems not quite worth the eye strain.

    You could generate a practically unique name for the property using cryptography:

    // get 1024 Unicode characters of gibberish
    var isMoving = SecureRandom.generateName();
    
    ...
    
    if (element[isMoving]) {
      smoothAnimations(element);
    }
    element[isMoving] = true;
    

    The object[name] syntax lets you use literally any string as a property name. So this will work: collisions are virtually impossible, and your code looks OK.

    But this is going to lead to a bad debugging experience. Every time you console.log() an element with that property on it, you’ll be looking a huge string of garbage. And what if you need more than one property like this? How do you keep them straight? They’ll have different names every time you reload.

    Why is this so hard? We just want one little boolean!

    Symbols are the answer

    Symbols are values that programs can create and use as property keys without risking name collisions.

    var mySymbol = Symbol();
    

    Calling Symbol() creates a new symbol, a value that’s not equal to any other value.

    Just like a string or number, you can use a symbol as a property key. Because it’s not equal to any string, this symbol-keyed property is guaranteed not to collide with any other property.

    obj[mySymbol] = "ok!";  // guaranteed not to collide
    console.log(obj[mySymbol]);  // ok!
    

    Here is how you could use a symbol in the situation discussed above:

    // create a unique symbol
    var isMoving = Symbol("isMoving");
    
    ...
    
    if (element[isMoving]) {
      smoothAnimations(element);
    }
    element[isMoving] = true;
    

    A few notes about this code:

    • The string "isMoving" in Symbol("isMoving") is called a description. It’s helpful for debugging. It’s shown when you write the symbol to console.log(), when you convert it to a string using .toString(), and possibly in error messages. That’s all.

    • element[isMoving] is called a symbol-keyed property. It’s simply a property whose name is a symbol rather than a string. Apart from that, it is in every way a normal property.

    • Like array elements, symbol-keyed properties can’t be accessed using dot syntax, as in obj.name. They must be accessed using square brackets.

    • It’s trivial to access a symbol-keyed property if you’ve already got the symbol. The above example shows how to get and set element[isMoving], and we could also ask if (isMoving in element) or even delete element[isMoving] if we needed to.

    • On the other hand, all of that is only possible as long as isMoving is in scope. This makes symbols a mechanism for weak encapsulation: a module that creates a few symbols for itself can use them on whatever objects it wants to, without fear of colliding with properties created by other code.

    Because symbol keys were designed to avoid collisions, JavaScript’s most common object-inspection features simply ignore symbol keys. A for-in loop, for instance, only loops over an object’s string keys. Symbol keys are skipped. Object.keys(obj) and Object.getOwnPropertyNames(obj) do the same. But symbols are not exactly private: it is possible to use the new API Object.getOwnPropertySymbols(obj) to list the symbol keys of an object. Another new API, Reflect.ownKeys(obj), returns both string and symbol keys. (We’ll discuss the Reflect API in full in an upcoming post.)

    Libraries and frameworks will likely find many uses for symbols, and as we’ll see later, the language itself is using of them for a wide range of purposes.

    But what are symbols, exactly?

    > typeof Symbol()
    "symbol"
    

    Symbols aren’t exactly like anything else.

    They’re immutable once created. You can’t set properties on them (and if you try that in strict mode, you’ll get a TypeError). They can be property names. These are all string-like qualities.

    On the other hand, each symbol is unique, distinct from all others (even others that have the same description) and you can easily create new ones. These are object-like qualities.

    ES6 symbols are similar to the more traditional symbols in languages like Lisp and Ruby, but not so closely integrated into the language. In Lisp, all identifiers are symbols. In JS, identifiers and most property keys are still considered strings. Symbols are just an extra option.

    One quick caveat about symbols: unlike almost anything else in the language, they can’t be automatically converted to strings. Trying to concatenate a symbol with strings will result in a TypeError.

    > var sym = Symbol("<3");
    > "your symbol is " + sym
    // TypeError: can't convert symbol to string
    > `your symbol is ${sym}`
    // TypeError: can't convert symbol to string
    

    You can avoid this by explicitly converting the symbol to a string, writing String(sym) or sym.toString().

    Three sets of symbols

    There are three ways to obtain a symbol.

    • Call Symbol(). As we already discussed, this returns a new unique symbol each time it’s called.

    • Call Symbol.for(string). This accesses a set of existing symbols called the symbol registry. Unlike the unique symbols defined by Symbol(), symbols in the symbol registry are shared. If you call Symbol.for("cat") thirty times, it will return the same symbol each time. The registry is useful when multiple web pages, or multiple modules within the same web page, need to share a symbol.

    • Use symbols like Symbol.iterator, defined by the standard. A few symbols are defined by the standard itself. Each one has its own special purpose.

    If you still aren’t sure if symbols will be all that useful, this last category is interesting, because they show how symbols have already proven useful in practice.

    How the ES6 spec is using well-known symbols

    We’ve already seen one way that ES6 uses a symbol to avoid conflicts with existing code. A few weeks ago, in the post on iterators, we saw that the loop for (var item of myArray) starts by calling myArray[Symbol.iterator](). I mentioned that this method could have been called myArray.iterator(), but a symbol is better for backward compatibility.

    Now that we know what symbols are all about, it’s easy to understand why this was done and what it means.

    Here are a few of the other places where ES6 uses well-known symbols. (These features are not implemented in Firefox yet.)

    • Making instanceof extensible. In ES6, the expression object instanceof constructor is specified as a method of the constructor: constructor[Symbol.hasInstance](object). This means it is extensible.

    • Eliminating conflicts between new features and old code. This is seriously obscure, but we found that certain ES6 Array methods broke existing web sites just by being there. Other Web standards had similar problems: simply adding new methods in the browser would break existing sites. However, the breakage was mainly caused by something called dynamic scoping, so ES6 introduces a special symbol, Symbol.unscopables, that Web standards can use to prevent certain methods from getting involved in dynamic scoping.

    • Supporting new kinds of string-matching. In ES5, str.match(myObject) tried to convert myObject to a RegExp. In ES6, it first checks to see if myObject has a method myObject[Symbol.match](str). Now libraries can provide custom string-parsing classes that work in all the places where RegExp objects work.

    Each of these uses is quite narrow. It’s hard to see any of these features by themselves having a major impact in my day-to-day code. The long view is more interesting. Well-known symbols are JavaScript’s improved version of the __doubleUnderscores in PHP and Python. The standard will use them in the future to add new hooks into the language with no risk to your existing code.

    When can I use ES6 symbols?

    Symbols are implemented in Firefox 36 and Chrome 38. I implemented them for Firefox myself, so if your symbols ever act like cymbals, you’ll know who to talk to.

    To support browsers that do not yet have native support for ES6 symbols, you can use a polyfill, such as core.js. Since symbols are not exactly like anything previously in the language, the polyfill isn’t perfect. Read the caveats.

    Next week, we’ll have two new posts. First, we’ll cover some long-awaited features that are finally coming to JavaScript in ES6—and complain about them. We’ll start with two features that date back almost to the dawn of programming. We’ll continue with two features that are very similar, but powered by ephemerons. So please join us next week as we look at ES6 collections in depth.

    And, stick around for a bonus post by Gastón Silva on a topic that isn’t an ES6 feature at all, but might provide the nudge you need to start using ES6 in your own projects. See you then!

  4. ES6 In Depth: Arrow functions

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    Arrows have been part of JavaScript from the very beginning. The first JavaScript tutorials advised wrapping inline scripts in HTML comments. This would prevent browsers that didn’t support JS from erroneously displaying your JS code as text. You would write something like this:

    <script language="javascript">
    <!--
      document.bgColor = "brown";  // red
    // -->
    </script>
    

    Old browsers would see two unsupported tags and a comment; only new browsers would see JS code.

    To support this odd hack, the JavaScript engine in your browser treats the characters <!-- as the start of a one-line comment. No joke. This has really been part of the language all along, and it works to this day, not just at the top of an inline <script> but everywhere in JS code. It even works in Node.

    As it happens, this style of comment is standardized for the first time in ES6. But this isn’t the arrow we’re here to talk about.

    The arrow sequence --> also denotes a one-line comment. Weirdly, while in HTML characters before the --> are part of the comment, in JS the rest of the line after the --> is a comment.

    It gets stranger. This arrow indicates a comment only when it appears at the start of a line. That’s because in other contexts, --> is an operator in JS, the “goes to” operator!

    function countdown(n) {
      while (n --> 0)  // "n goes to zero"
        alert(n);
      blastoff();
    }
    

    This code really works. The loop runs until n gets to 0. This too is not a new feature in ES6, but a combination of familiar features, with a little misdirection thrown in. Can you figure out what’s going on here? As usual, the answer to the puzzle can be found on Stack Overflow.

    Of course there is also the less-than-or-equal-to operator, <=. Perhaps you can find more arrows in your JS code, Hidden Pictures style, but let’s stop here and observe that an arrow is missing.

    <!-- single-line comment
    --> “goes to” operator
    <= less than or equal to
    => ???

    What happened to =>? Today, we find out.

    First, let’s talk a bit about functions.

    Function expressions are everywhere

    A fun feature of JavaScript is that any time you need a function, you can just type that function right in the middle of running code.

    For example, suppose you are trying to tell the browser what to do when the user clicks on a particular button. You start typing:

    $("#confetti-btn").click(
    

    jQuery’s .click() method takes one argument: a function. No problem. You can just type in a function right here:

    $("#confetti-btn").click(function (event) {
      playTrumpet();
      fireConfettiCannon();
    });
    

    Writing code like this comes quite naturally to us now. So it’s strange to recall that before JavaScript popularized this kind of programming, many languages did not have this feature. Of course Lisp had function expressions, also called lambda functions, in 1958. But C++, Python, C#, and Java all existed for years without them.

    Not anymore. All four have lambdas now. Newer languages universally have lambdas built in. We have JavaScript to thank for this—and early JavaScript programmers who fearlessly built libraries that depended heavily on lambdas, leading to widespread adoption of the feature.

    It is just slightly sad, then, that of all the languages I’ve mentioned, JavaScript’s syntax for lambdas has turned out to be the wordiest.

    // A very simple function in six languages.
    function (a) { return a > 0; } // JS
    [](int a) { return a > 0; }  // C++
    (lambda (a) (> a 0))  ;; Lisp
    lambda a: a > 0  # Python
    a => a > 0  // C#
    a -> a > 0  // Java
    

    A new arrow in your quiver

    ES6 introduces a new syntax for writing functions.

    // ES5
    var selected = allJobs.filter(function (job) {
      return job.isSelected();
    });
    
    // ES6
    var selected = allJobs.filter(job => job.isSelected());
    

    When you just need a simple function with one argument, the new arrow function syntax is simply Identifier => Expression. You get to skip typing function and return, as well as some parentheses, braces, and a semicolon.

    (I am personally very grateful for this feature. Not having to type function is important to me, because I inevitably type functoin instead and have to go back and correct it.)

    To write a function with multiple arguments (or no arguments, or rest parameters or defaults, or a destructuring argument) you’ll need to add parentheses around the argument list.

    // ES5
    var total = values.reduce(function (a, b) {
      return a + b;
    }, 0);
    
    // ES6
    var total = values.reduce((a, b) => a + b, 0);
    

    I think it looks pretty nice.

    Arrow functions work just as beautifully with functional tools provided by libraries, like Underscore.js and Immutable. In fact, the examples in Immutable’s documentation are all written in ES6, so many of them already use arrow functions.

    What about not-so-functional settings? Arrow functions can contain a block of statements instead of just an expression. Recall our earlier example:

    // ES5
    $("#confetti-btn").click(function (event) {
      playTrumpet();
      fireConfettiCannon();
    });
    

    Here’s how it will look in ES6:

    // ES6
    $("#confetti-btn").click(event => {
      playTrumpet();
      fireConfettiCannon();
    });
    

    A minor improvement. The effect on code using Promises can be more dramatic, as the }).then(function (result) { lines can pile up.

    Note that an arrow function with a block body does not automatically return a value. Use a return statement for that.

    There is one caveat when using arrow functions to create plain objects. Always wrap the object in parentheses:

    // create a new empty object for each puppy to play with
    var chewToys = puppies.map(puppy => {});   // BUG!
    var chewToys = puppies.map(puppy => ({})); // ok
    

    Unfortunately, an empty object {} and an empty block {} look exactly the same. The rule in ES6 is that { immediately following an arrow is always treated as the start of a block, never the start of an object. The code puppy => {} is therefore silently interpreted as an arrow function that does nothing and returns undefined.

    Even more confusing, an object literal like {key: value} looks exactly like a block containing a labeled statement—at least, that’s how it looks to your JavaScript engine. Fortunately { is the only ambiguous character, so wrapping object literals in parentheses is the only trick you need to remember.

    What’s this?

    There is one subtle difference in behavior between ordinary function functions and arrow functions. Arrow functions do not have their own this value. The value of this inside an arrow function is always inherited from the enclosing scope.

    Before we try and figure out what that means in practice, let’s back up a bit.

    How does this work in JavaScript? Where does its value come from? There’s no short answer. If it seems simple in your head, it’s because you’ve been dealing with it for a long time!

    One reason this question comes up so often is that function functions receive a this value automatically, whether they want one or not. Have you ever written this hack?

    {
      ...
      addAll: function addAll(pieces) {
        var self = this;
        _.each(pieces, function (piece) {
          self.add(piece);
        });
      },
      ...
    }
    

    Here, what you’d like to write in the inner function is just this.add(piece). Unfortunately, the inner function doesn’t inherit the outer function’s this value. Inside the inner function, this will be window or undefined. The temporary variable self serves to smuggle the outer value of this into the inner function. (Another way is to use .bind(this) on the inner function. Neither way is particularly pretty.)

    In ES6, this hacks mostly go away if you follow these rules:

    • Use non-arrow functions for methods that will be called using the object.method() syntax. Those are the functions that will receive a meaningful this value from their caller.
    • Use arrow functions for everything else.
    // ES6
    {
      ...
      addAll: function addAll(pieces) {
        _.each(pieces, piece => this.add(piece));
      },
      ...
    }
    

    In the ES6 version, note that the addAll method receives this from its caller. The inner function is an arrow function, so it inherits this from the enclosing scope.

    As a bonus, ES6 also provides a shorter way to write methods in object literals! So the code above can be simplified further:

    // ES6 with method syntax
    {
      ...
      addAll(pieces) {
        _.each(pieces, piece => this.add(piece));
      },
      ...
    }
    

    Between methods and arrows, I might never type functoin again. It’s a nice thought.

    There’s one more minor difference between arrow and non-arrow functions: arrow functions don’t get their own arguments object, either. Of course, in ES6, you’d probably rather use a rest parameter or default value anyway.

    Using arrows to pierce the dark heart of computer science

    We’ve talked about the many practical uses of arrow functions. There’s one more possible use case I’d like to talk about: ES6 arrow functions as a learning tool, to uncover something deep about the nature of computation. Whether that is practical or not, you’ll have to decide for yourself.

    In 1936, Alonzo Church and Alan Turing independently developed powerful mathematical models of computation. Turing called his model a-machines, but everyone instantly started calling them Turing machines. Church wrote instead about functions. His model was called the λ-calculus. (λ is the lowercase Greek letter lambda.) This work was the reason Lisp used the word LAMBDA to denote functions, which is why we call function expressions “lambdas” today.

    But what is the λ-calculus? What is “model of computation” supposed to mean?

    It’s hard to explain in just a few words, but here is my attempt: the λ-calculus is one of the first programming languages. It was not designed to be a programming language—after all, stored-program computers wouldn’t come along for another decade or two—but rather a ruthlessly simple, stripped-down, purely mathematical idea of a language that could express any kind of computation you wished to do. Church wanted this model in order to prove things about computation in general.

    And he found that he only needed one thing in his system: functions.

    Think how extraordinary this claim is. Without objects, without arrays, without numbers, without if statements, while loops, semicolons, assignment, logical operators, or an event loop, it is possible to rebuild every kind of computation JavaScript can do, from scratch, using only functions.

    Here is an example of the sort of “program” a mathematician could write, using Church’s λ notation:

    fix = λf.(λx.f(λv.x(x)(v)))(λx.f(λv.x(x)(v)))
    

    The equivalent JavaScript function looks like this:

    var fix = f => (x => f(v => x(x)(v)))
                   (x => f(v => x(x)(v)));
    

    That is, JavaScript contains an implementation of the λ-calculus that actually runs. The λ-calculus is in JavaScript.

    The stories of what Alonzo Church and later researchers did with the λ-calculus, and how it has quietly insinuated itself into almost every major programming language, are beyond the scope of this blog post. But if you’re interested in the foundations of computer science, or you’d just like to see how a language with nothing but functions can do things like loops and recursion, you could do worse than to spend some rainy afternoon looking into Church numerals and fixed-point combinators, and playing with them in your Firefox console or Scratchpad. With ES6 arrows on top of its other strengths, JavaScript can reasonably claim to be the best language for exploring the λ-calculus.

    When can I use arrows?

    ES6 arrow functions were implemented in Firefox by me, back in 2013. Jan de Mooij made them fast. Thanks to Tooru Fujisawa and ziyunfei for patches.

    Arrow functions are also implemented in the Microsoft Edge preview release. They’re also available in Babel, Traceur, and TypeScript, in case you’re interested in using them on the Web right now.

    Our next topic is one of the stranger features in ES6. We’ll get to see typeof x return a totally new value. We’ll ask: When is a name not a string? We’ll puzzle over the meaning of equality. It’ll be weird. So please join us next week as we look at ES6 symbols in depth.

  5. Power Surge – optimize the JavaScript in this HTML5 game using Firefox Developer Edition

    Power Surge!

    The Firefox Developer Tools team wanted to find a fun way to show off the great performance tools we’ve just added to the Firefox Developer Edition browser. We partnered with Przemysław Sikorski (aka rezoner) author of Playground.js and the arcade puzzle game QbQbQb, to create “Power Surge,” a fun game which shows off how the new Performance tools can help developers find slow JavaScript code. The special twist is that the more you optimize the code in the game, the more ships and powers you win in gameplay!

    First off, check out this quick screencast from Mozilla engineer Harald Kirschner on how Power Surge works:

    To get going with Power Surge:

    We’d really like to hear back from you about Power Surge! Tweet to us at @FirefoxDevtools and @mozhacks to share your solutions.

  6. ES6 In Depth: Destructuring

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    Editor’s note: An earlier version of today’s post, by Firefox Developer Tools engineer Nick Fitzgerald, originally appeared on Nick’s blog as Destructuring Assignment in ES6.

    What is destructuring assignment?

    Destructuring assignment allows you to assign the properties of an array or object to variables using syntax that looks similar to array or object literals. This syntax can be extremely terse, while still exhibiting more clarity than the traditional property access.

    Without destructuring assignment, you might access the first three items in an array like this:

    var first = someArray[0];
    var second = someArray[1];
    var third = someArray[2];
    

    With destructuring assignment, the equivalent code becomes more concise and readable:

    var [first, second, third] = someArray;
    

    SpiderMonkey (Firefox’s JavaScript engine) already has support for most of destructuring, but not quite all of it. Track SpiderMonkey’s destructuring (and general ES6) support in bug 694100.

    Destructuring arrays and iterables

    We already saw one example of destructuring assignment on an array above. The general form of the syntax is:

    [ variable1, variable2, ..., variableN ] = array;
    

    This will just assign variable1 through variableN to the corresponding item in the array. If you want to declare your variables at the same time, you can add a var, let, or const in front of the assignment:

    var [ variable1, variable2, ..., variableN ] = array;
    let [ variable1, variable2, ..., variableN ] = array;
    const [ variable1, variable2, ..., variableN ] = array;
    

    In fact, variable is a misnomer since you can nest patterns as deep as you would like:

    var [foo, [[bar], baz]] = [1, [[2], 3]];
    console.log(foo);
    // 1
    console.log(bar);
    // 2
    console.log(baz);
    // 3
    

    Furthermore, you can skip over items in the array being destructured:

    var [,,third] = ["foo", "bar", "baz"];
    console.log(third);
    // "baz"
    

    And you can capture all trailing items in an array with a “rest” pattern:

    var [head, ...tail] = [1, 2, 3, 4];
    console.log(tail);
    // [2, 3, 4]
    

    When you access items in the array that are out of bounds or don’t exist, you get the same result you would by indexing: undefined.

    console.log([][0]);
    // undefined
    
    var [missing] = [];
    console.log(missing);
    // undefined
    

    Note that destructuring assignment with an array assignment pattern also works for any iterable:

    function* fibs() {
      var a = 0;
      var b = 1;
      while (true) {
        yield a;
        [a, b] = [b, a + b];
      }
    }
    
    var [first, second, third, fourth, fifth, sixth] = fibs();
    console.log(sixth);
    // 5
    

    Destructuring objects

    Destructuring on objects lets you bind variables to different properties of an object. You specify the property being bound, followed by the variable you are binding its value to.

    var robotA = { name: "Bender" };
    var robotB = { name: "Flexo" };
    
    var { name: nameA } = robotA;
    var { name: nameB } = robotB;
    
    console.log(nameA);
    // "Bender"
    console.log(nameB);
    // "Flexo"
    

    There is a helpful syntactical shortcut for when the property and variable names are the same:

    var { foo, bar } = { foo: "lorem", bar: "ipsum" };
    console.log(foo);
    // "lorem"
    console.log(bar);
    // "ipsum"
    

    And just like destructuring on arrays, you can nest and combine further destructuring:

    var complicatedObj = {
      arrayProp: [
        "Zapp",
        { second: "Brannigan" }
      ]
    };
    
    var { arrayProp: [first, { second }] } = complicatedObj;
    
    console.log(first);
    // "Zapp"
    console.log(second);
    // "Brannigan"
    

    When you destructure on properties that are not defined, you get undefined:

    var { missing } = {};
    console.log(missing);
    // undefined
    

    One potential gotcha you should be aware of is when you are using destructuring on an object to assign variables, but not to declare them (when there is no let, const, or var):

    { blowUp } = { blowUp: 10 };
    // Syntax error
    

    This happens because the JavaScript grammar tells the engine to parse any statement starting with { as a block statement (for example, { console } is a valid block statement). The solution is to either wrap the whole expression in parentheses:

    ({ safe } = {});
    // No errors
    

    Destructuring values that are not an object, array, or iterable

    When you try to use destructuring on null or undefined, you get a type error:

    var {blowUp} = null;
    // TypeError: null has no properties
    

    However, you can destructure on other primitive types such as booleans, numbers, and strings, and get undefined:

    var {wtf} = NaN;
    console.log(wtf);
    // undefined
    

    This may come unexpected, but upon further examination the reason turns out to be simple. When using an object assignment pattern, the value being destructured is required to be coercible to an Object. Most types can be converted to an object, but null and undefined may not be converted. When using an array assignment pattern, the value must have an iterator.

    Default values

    You can also provide default values for when the property you are destructuring is not defined:

    var [missing = true] = [];
    console.log(missing);
    // true
    
    var { message: msg = "Something went wrong" } = {};
    console.log(msg);
    // "Something went wrong"
    
    var { x = 3 } = {};
    console.log(x);
    // 3
    

    (Editor’s note: This feature is currently implemented in Firefox only for the first two cases, not the third. See bug 932080.)

    Practical applications of destructuring

    Function parameter definitions

    As developers, we can often expose more ergonomic APIs by accepting a single object with multiple properties as a parameter instead of forcing our API consumers to remember the order of many individual parameters. We can use destructuring to avoid repeating this single parameter object whenever we want to reference one of its properties:

    function removeBreakpoint({ url, line, column }) {
      // ...
    }
    

    This is a simplified snippet of real world code from the Firefox DevTools JavaScript debugger (which is also implemented in JavaScript—yo dawg). We have found this pattern particularly pleasing.

    Configuration object parameters

    Expanding on the previous example, we can also give default values to the properties of the objects we are destructuring. This is particularly helpful when we have an object that is meant to provide configuration and many of the object’s properties already have sensible defaults. For example, jQuery’s ajax function takes a configuration object as its second parameter, and could be rewritten like this:

    jQuery.ajax = function (url, {
      async = true,
      beforeSend = noop,
      cache = true,
      complete = noop,
      crossDomain = false,
      global = true,
      // ... more config
    }) {
      // ... do stuff
    };
    

    This avoids repeating var foo = config.foo || theDefaultFoo; for each property of the configuration object.

    (Editor’s note: Unfortunately, default values within object shorthand syntax still aren’t implemented in Firefox. I know, we’ve had several paragraphs to work on it since that earlier note. See bug 932080 for the latest updates.)

    With the ES6 iteration protocol

    ECMAScript 6 also defines an iteration protocol, which we talked about earlier in this series. When you iterate over Maps (an ES6 addition to the standard library), you get a series of [key, value] pairs. We can destructure this pair to get easy access to both the key and the value:

    var map = new Map();
    map.set(window, "the global");
    map.set(document, "the document");
    
    for (var [key, value] of map) {
      console.log(key + " is " + value);
    }
    // "[object Window] is the global"
    // "[object HTMLDocument] is the document"
    

    Iterate over only the keys:

    for (var [key] of map) {
      // ...
    }
    

    Or iterate over only the values:

    for (var [,value] of map) {
      // ...
    }
    

    Multiple return values

    Although multiple return values aren’t baked into the language proper, they don’t need to be because you can return an array and destructure the result:

    function returnMultipleValues() {
      return [1, 2];
    }
    var [foo, bar] = returnMultipleValues();
    

    Alternatively, you can use an object as the container and name the returned values:

    function returnMultipleValues() {
      return {
        foo: 1,
        bar: 2
      };
    }
    var { foo, bar } = returnMultipleValues();
    

    Both of these patterns end up much better than holding onto the temporary container:

    function returnMultipleValues() {
      return {
        foo: 1,
        bar: 2
      };
    }
    var temp = returnMultipleValues();
    var foo = temp.foo;
    var bar = temp.bar;
    

    Or using continuation passing style:

    function returnMultipleValues(k) {
      k(1, 2);
    }
    returnMultipleValues((foo, bar) => ...);
    

    Importing names from a CommonJS module

    Not using ES6 modules yet? Still using CommonJS modules? No problem! When importing some CommonJS module X, it is fairly common that module X exports more functions than you actually intend to use. With destructuring, you can be explicit about which parts of a given module you’d like to use and avoid cluttering your namespace:

    const { SourceMapConsumer, SourceNode } = require("source-map");
    

    (And if you do use ES6 modules, you know that a similar syntax is available in import declarations.)

    Conclusion

    So, as you can see, destructuring is useful in many individually small cases. At Mozilla we’ve had a lot of experience with it. Lars Hansen introduced JS destructuring in Opera ten years ago, and Brendan Eich added support to Firefox a bit later. It shipped in Firefox 2. So we know that destructuring sneaks into your everyday use of the language, quietly making your code a bit shorter and cleaner all over the place.

    Five weeks ago, we said that ES6 would change the way you write JavaScript. It is this sort of feature we had particularly in mind: simple improvements that can be learned one at a time. Taken together, they will end up affecting every project you work on. Revolution by way of evolution.

    Updating destructuring to comply with ES6 has been a team effort. Special thanks to Tooru Fujisawa (arai) and Arpad Borsos (Swatinem) for their excellent contributions.

    Support for destructuring is under development for Chrome, and other browsers will undoubtedly add support in time. For now, you’ll need to use Babel or Traceur if you want to use destructuring on the Web.


    Thanks again to Nick Fitzgerald for this week’s post.

    Next week, we’ll cover a feature that is nothing more or less than a slightly shorter way to write something JS already has—something that has been one of the fundamental building blocks of the language all along. Will you care? Is slightly shorter syntax something you can get excited about? I confidently predict the answer is yes, but don’t take my word for it. Join us next week and find out, as we look at ES6 arrow functions in depth.

    Jason Orendorff

    ES6 In Depth editor

  7. ES6 In Depth: Rest parameters and defaults

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    Today’s post is about two features that make JavaScript’s function syntax more expressive: rest parameters and parameter defaults.

    Rest parameters

    A common need when creating an API is a variadic function, a function that accepts any number of arguments. For example, the String.prototype.concat method takes any number of string arguments. With rest parameters, ES6 provides a new way to write variadic functions.

    To demonstrate, let’s write a simple variadic function containsAll that checks whether a string contains a number of substrings. For example, containsAll("banana", "b", "nan") would return true, and containsAll("banana", "c", "nan") would return false.

    Here is the traditional way to implement this function:

    function containsAll(haystack) {
      for (var i = 1; i < arguments.length; i++) {
        var needle = arguments[i];
        if (haystack.indexOf(needle) === -1) {
          return false;
        }
      }
      return true;
    }
    

    This implementation uses the magical arguments object, an array-like object containing the parameters passed to the function. This code certainly does what we want, but its readibility is not optimal. The function parameter list contains only one parameter haystack, so it’s impossible to tell at a glance that the function actually takes multiple arguments. Additionally, we must be careful to start iterating through arguments at index 1 not 0, since arguments[0] corresponds to the haystack argument. If we ever wanted to add another parameter before or after haystack, we would have to remember to update the for loop. Rest parameters address both of these concerns. Here is a natural ES6 implementation of containsAll using a rest parameter:

    function containsAll(haystack, ...needles) {
      for (var needle of needles) {
        if (haystack.indexOf(needle) === -1) {
          return false;
        }
      }
      return true;
    }
    

    This version of the function has the same behavior as the first one but contains the special ...needles syntax. Let’s see how calling this function works for the invocation containsAll("banana", "b", "nan"). The argument haystack is filled as usual with the parameter that is passed first, namely "banana". The ellipsis before needles indicates it is a rest parameter. All the other passed parameters are put into an array and assigned to the variable needles. For our example call, needles is set to ["b", "nan"]. Function execution then continues as normal. (Notice we have used the ES6 for-of looping construct.)

    Only the last parameter of a function may be marked as a rest parameter. In a call, the parameters before the rest parameter are filled as usual. Any “extra” arguments are put into an array and assigned to the rest parameter. If there are no extra arguments, the rest parameter will simply be an empty array; the rest parameter will never be undefined.

    Default parameters

    Often, a function doesn’t need to have all its possible parameters passed by callers, and there are sensible defaults that could be used for parameters that are not passed. JavaScript has always had a inflexible form of default parameters; parameters for which no value is passed default to undefined. ES6 introduces a way to specify arbitrary parameter defaults.

    Here’s an example. (The backticks signify template strings, which were discussed last week.)

    function animalSentence(animals2="tigers", animals3="bears") {
        return `Lions and ${animals2} and ${animals3}! Oh my!`;
    }
    

    For each parameter, the part after the = is an expression specifying the default value of the parameter if a caller does not pass it. So, animalSentence() returns "Lions and tigers and bears! Oh my!", animalSentence("elephants") returns "Lions and elephants and bears! Oh my!", and animalSentence("elephants", "whales") returns "Lions and elephants and whales! Oh my!".

    The are several subtleties related to default parameters:

    • Unlike Python, default value expressions are evaluated at function call time from left to right. This also means that default expressions can use the values of previously-filled parameters. For example, we could make our animal sentence function more fancy as follows:
      function animalSentenceFancy(animals2="tigers",
          animals3=(animals2 == "bears") ? "sealions" : "bears")
      {
        return `Lions and ${animals2} and ${animals3}! Oh my!`;
      }
      

      Then, animalSentenceFancy("bears") returns "Lions and bears and sealions. Oh my!".

    • Passing undefined is considered to be equivalent to not passing anything at all. Thus, animalSentence(undefined, "unicorns") returns "Lions and tigers and unicorns! Oh my!".
    • A parameter without a default implicitly defaults to undefined, so
      function myFunc(a=42, b) {...}
      

      is allowed and equivalent to

      function myFunc(a=42, b=undefined) {...}
      

    Shutting down arguments

    We’ve now seen that rest parameters and defaults can replace usage of the arguments object, and removing arguments usually makes the code nicer to read. In addition to harming readibility, the magic of the arguments object notoriously causes headaches for optimizing JavaScript VMs.

    It is hoped that rest parameters and defaults can completely supersede arguments. As a first step towards this, functions that use a rest parameter or defaults are forbidden from using the arguments object. Support for arguments won’t be removed soon, if ever, but it’s now preferable to avoid arguments with rest parameters and defaults when possible.

    Browser support

    Firefox has had support for rest parameters and defaults since version 15.

    Unfortunately, no other released browser supports rest parameters or defaults yet. V8 recently added experimental support for rest parameters, and there is an open V8 issue for implementing defaults. JSC also has open issues for rest parameters and defaults.

    The Babel and Traceur compilers both support default parameters, so it is possible to start using them today.

    Conclusion

    Although technically not allowing any new behavior, rest parameters and parameter defaults can make some JavaScript function declarations more expressive and readable. Happy calling!


    Note: Thanks to Benjamin Peterson for implementing these features in Firefox, for all his contributions to the project, and of course for this week’s post.

    Next week, we’ll introduce another simple, elegant, practical, everyday ES6 feature. It takes the familiar syntax you already use to write arrays and objects, and turns it on its head, producing a new, concise way to take arrays and objects apart. What does that mean? Why would you want to take an object apart? Join us next Thursday to find out, as Mozilla engineer Nick Fitzgerald presents ES6 destructuring in depth.

    Jason Orendorff

    ES6 In Depth editor

  8. ES6 In Depth: Template strings

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    Last week I promised a change of pace. After iterators and generators, we would tackle something easy, I said. Something that won’t melt your brain, I said. We’ll see whether I can keep that promise in the end.

    For now, let’s start with something simple.

    Backtick basics

    ES6 introduces a new kind of string literal syntax called template strings. They look like ordinary strings, except using the backtick character ` rather than the usual quote marks ' or ". In the simplest case, they really are just strings:

    context.fillText(`Ceci n'est pas une chaîne.`, x, y);
    

    But there’s a reason these are called “template strings” and not “boring plain old strings that don’t do anything special, only with backticks”. Template strings bring simple string interpolation to JavaScript. That is, they’re a nice-looking, convenient way to plug JavaScript values into a string.

    There are one million ways to use this, but the one that warms my heart is the humble error message:

    function authorize(user, action) {
      if (!user.hasPrivilege(action)) {
        throw new Error(
          `User ${user.name} is not authorized to do ${action}.`);
      }
    }
    

    In this example, ${user.name} and ${action} are called template substitutions. JavaScript will plug the values user.name and action into the resulting string. This could generate a message like User jorendorff is not authorized to do hockey. (Which is true. I don’t have a hockey license.)

    So far, this is just a slightly nicer syntax for the + operator, and the details are what you would expect:

    • The code in a template substitution can be any JavaScript expression, so function calls, arithmetic, and so on are allowed. (If you really want to, you can even nest a template string inside another template string, which I call template inception.)
    • If either value is not a string, it’ll be converted to a string using the usual rules. For example, if action is an object, its .toString() method will be called.
    • If you need to write a backtick inside a template string, you must escape it with a backslash: `\`` is the same as "`".
    • Likewise, if you need to include the two characters ${ in a template string, I don’t want to know what you’re up to, but you can escape either character with a backslash: `write \${ or $\{`.

    Unlike ordinary strings, template strings can cover multiple lines:

    $("#warning").html(`
      <h1>Watch out!</h1>
      <p>Unauthorized hockeying can result in penalties
      of up to ${maxPenalty} minutes.</p>
    `);
    

    All whitespace in the template string, including newlines and indentation, is included verbatim in the output.

    OK. Because of my promise last week, I feel responsible for your brain health. So a quick warning: it starts getting a little intense from here. You can stop reading now, maybe go have a cup of coffee and enjoy your intact, unmelted brain. Seriously, there’s no shame in turning back. Did Lopes Gonçalves exhaustively explore the entire Southern Hemisphere after proving that ships can cross the equator without being crushed by sea monsters or falling off the edge of the earth? No. He turned back, went home, and had a nice lunch. You like lunch, right?

    Backtick the future

    Let’s talk about a few things template strings don’t do.

    • They don’t automatically escape special characters for you. To avoid cross-site scripting vulnerabilities, you’ll still have to treat untrusted data with care, just as if you were concatenating ordinary strings.
    • It’s not obvious how they would interact with an internationalization library (a library for helping your code speak different languages to different users). Template strings don’t handle language-specific formatting of numbers and dates, much less plurals.
    • They aren’t a replacement for template libraries, like Mustache or Nunjucks.

      Template strings don’t have any built-in syntax for looping—building the rows of an HTML table from an array, for example—or even conditionals. (Yes, you could use template inception for this, but to me it seems like the sort of thing you’d do as a joke.)

    ES6 provides one more twist on template strings that gives JS developers and library designers the power to address these limitations and more. The feature is called tagged templates.

    The syntax for tagged templates is simple. They’re just template strings with an extra tag before the opening backtick. For our first example, the tag will be SaferHTML, and we’re going to use this tag to try to address the first limitation listed above: automatically escaping special characters.

    Note that SaferHTML is not something provided by the ES6 standard library. We’re going to implement it ourselves below.

    var message =
      SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>`;
    

    The tag here is the single identifier SaferHTML, but a tag can also be a property, like SaferHTML.escape, or even a method call, like SaferHTML.escape({unicodeControlCharacters: false}). (To be precise, any ES6 MemberExpression or CallExpression can serve as a tag.)

    We saw that untagged template strings are shorthand for simple string concatenation. Tagged templates are shorthand for something else entirely: a function call.

    The code above is equivalent to:

    var message =
      SaferHTML(templateData, bonk.sender);
    

    where templateData is an immutable array of all the string parts of the template, created for us by the JS engine. Here the array would have two elements, because there are two string parts in the tagged template, separated by a substitution. So templateData will be like Object.freeze(["<p>", " has sent you a bonk.</p>"].

    (There is actually one more property present on templateData. We won’t use it in this article, but I’ll mention it for completeness: templateData.raw is another array containing all the string parts in the tagged template, but this time exactly as they looked in the source code—with escape sequences like \n left intact, rather than being turned into newlines and so on. The standard tag String.raw uses these raw strings.)

    This gives the SaferHTML function free rein to interpret both the string and the substitutions in a million possible ways.

    Before reading on, maybe you’d like to try to puzzle out just what SaferHTML should do, and then try your hand at implementing it. After all, it’s just a function. You can test your work in the Firefox developer console.

    Here is one possible answer (also available as a gist).

    function SaferHTML(templateData) {
      var s = templateData[0];
      for (var i = 1; i < arguments.length; i++) {
        var arg = String(arguments[i]);
    
        // Escape special characters in the substitution.
        s += arg.replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;");
    
        // Don't escape special characters in the template.
        s += templateData[i];
      }
      return s;
    }
    

    With this definition, the tagged template SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>` might expand to the string "<p>ES6&lt;3er has sent you a bonk.</p>". Your users are safe even if a maliciously named user, like Hacker Steve <script>alert('xss');</script>, sends them a bonk. Whatever that means.

    (Incidentally, if the way that function uses the arguments object strikes you as a bit clunky, drop by next week. There’s another new feature in ES6 that I think you’ll like.)

    A single example isn’t enough to illustrate the flexibility of tagged templates. Let’s revisit our earlier list of template string limitations to see what else you could do.

    • Template strings don’t auto-escape special characters. But as we’ve seen, with tagged templates, you can fix that problem yourself with a tag.

      In fact, you can do a lot better than that.

      From a security perspective, my SaferHTML function is pretty weak. Different places in HTML have different special characters that need to be escaped in different ways; SaferHTML does not escape them all. But with some effort, you could write a much smarter SaferHTML function that actually parses the bits of HTML in the strings in templateData, so that it knows which substitutions are in plain HTML; which ones are inside element attributes, and thus need to escape ' and "; which ones are in URL query strings, and thus need URL-escaping rather than HTML-escaping; and so on. It could perform just the right escaping for each substitution.

      Does this sound far-fetched because HTML parsing is slow? Fortunately, the string parts of a tagged template do not change when the template is evaluated again. SaferHTML could cache the results of all this parsing, to speed up later calls. (The cache could be a WeakMap, another ES6 feature that we’ll discuss in a future post.)

    • Template strings don’t have built-in internationalization features. But with tags, we could add them. A blog post by Jack Hsu shows what the first steps down that road might look like. Just one example, as a teaser:
      i18n`Hello ${name}, you have ${amount}:c(CAD) in your bank account.`
      // => Hallo Bob, Sie haben 1.234,56 $CA auf Ihrem Bankkonto.
      

      Note how in this example, name and amount are JavaScript, but there’s a different bit of unfamiliar code, that :c(CAD), which Jack places in the string part of the template. JavaScript is of course handled by the JavaScript engine; the string parts are handled by Jack’s i18n tag. Users would learn from the i18n documentation that :c(CAD) means amount is an amount of currency, denominated in Canadian dollars.

      This is what tagged templates are about.

    • Template strings are no replacement for Mustache and Nunjucks, partly because they don’t have built-in syntax for loops or conditionals. But now we’re starting to see how you would go about fixing this, right? If JS doesn’t provide the feature, write a tag that provides it.
      // Purely hypothetical template language based on
      // ES6 tagged templates.
      var libraryHtml = hashTemplate`
        <ul>
          #for book in ${myBooks}
            <li><i>#{book.title}</i> by #{book.author}</li>
          #end
        </ul>
      `;
      

    The flexibility doesn’t stop there. Note that the arguments to a tag function are not automatically converted to strings. They can be anything. The same goes for the return value. Tagged templates are not even necessarily strings! You could use custom tags to create regular expressions, DOM trees, images, promises representing whole asynchronous processes, JS data structures, GL shaders…

    Tagged templates invite library designers to create powerful domain-specific languages. These languages might look nothing like JS, but they can still embed in JS seamlessly and interact intelligently with the rest of the language. Offhand, I can’t think of anything quite like it in any other language. I don’t know where this feature will take us. The possibilities are exciting.

    When can I start using this?

    On the server, ES6 template strings are supported in io.js today.

    In browsers, Firefox 34+ supports template strings. They were implemented by Guptha Rajagopal as an intern project last summer. Template strings are also supported in Chrome 41+, but not in IE or Safari. For now, you’ll need to use Babel or Traceur if you want to use template strings on the web. You can also use them right now in TypeScript!

    Wait—what about Markdown?

    Hmm?

    Oh. …Good question.

    (This section isn’t really about JavaScript. If you don’t use Markdown, you can skip it.)

    With template strings, both Markdown and JavaScript now use the ` character to mean something special. In fact, in Markdown, it’s the delimiter for code snippets in the middle of inline text.

    This brings up a bit of a problem! If you write this in a Markdown document:

    To display a message, write `alert(`hello world!`)`.

    it’ll be displayed like this:

    To display a message, write alert(hello world!).

    Note that there are no backticks in the output. Markdown interpreted all four backticks as code delimiters and replaced them with HTML tags.

    To avoid this, we turn to a little-known feature that’s been in Markdown from the beginning: you can use multiple backticks as code delimiters, like this:

    To display a message, write ``alert(`hello world!`)``.

    This Gist has the details, and it’s written in Markdown so you can look at the source.

    Up next

    Next week, we’ll look at two features that programmers have enjoyed in other languages for decades: one for people who like to avoid an argument where possible, and one for people who like to have lots of arguments. I’m talking about function arguments, of course. Both features are really for all of us.

    We’ll see these features through the eyes of the person who implemented them in Firefox. So please join us next week, as guest author Benjamin Peterson presents ES6 default parameters and rest parameters in depth.

  9. ES6 In Depth: Generators

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    I’m excited about today’s post. Today, we’re going to discuss the most magical feature in ES6.

    What do I mean by “magical”? For starters, this feature is so different from things that already existed in JS that it may seem completely arcane at first. In a sense, it turns the normal behavior of the language inside out! If that’s not magic, I don’t know what is.

    Not only that: this feature’s power to simplify code and straighten out “callback hell” borders on the supernatural.

    Am I laying it on a bit thick? Let’s dive in and you can judge for yourself.

    Introducing ES6 generators

    What are generators?

    Let’s start by looking at one.

    function* quips(name) {
      yield "hello " + name + "!";
      yield "i hope you are enjoying the blog posts";
      if (name.startsWith("X")) {
        yield "it's cool how your name starts with X, " + name;
      }
      yield "see you later!";
    }
    

    This is some code for a talking cat, possibly the most important kind of application on the Internet today. (Go ahead, click the link, play with the cat. When you’re thoroughly confused, come back here for the explanation.)

    It looks sort of like a function, right? This is called a generator-function and it has a lot in common with functions. But you can see two differences right away:

    • Regular functions start with function. Generator-functions start with function*.

    • Inside a generator-function, yield is a keyword, with syntax rather like return. The difference is that while a function (even a generator-function) can only return once, a generator-function can yield any number of times. The yield expression suspends execution of the generator so it can be resumed again later.

    So that’s it, that’s the big difference between regular functions and generator-functions. Regular functions can’t pause themselves. Generator-functions can.

    What generators do

    What happens when you call the quips() generator-function?

    > var iter = quips("jorendorff");
      [object Generator]
    > iter.next()
      { value: "hello jorendorff!", done: false }
    > iter.next()
      { value: "i hope you are enjoying the blog posts", done: false }
    > iter.next()
      { value: "see you later!", done: false }
    > iter.next()
      { value: undefined, done: true }
    

    You’re probably very used to ordinary functions and how they behave. When you call them, they start running right away, and they run until they either return or throw. All this is second nature to any JS programmer.

    Calling a generator looks just the same: quips("jorendorff"). But when you call a generator, it doesn’t start running yet. Instead, it returns a paused Generator object (called iter in the example above). You can think of this Generator object as a function call, frozen in time. Specifically, it’s frozen right at the top of the generator-function, just before running its first line of code.

    Each time you call the Generator object’s .next() method, the function call thaws itself out and runs until it reaches the next yield expression.

    That’s why each time we called iter.next() above, we got a different string value. Those are the values produced by the yield expressions in the body of quips().

    On the last iter.next() call, we finally reached the end of the generator-function, so the .done field of the result is true. Reaching the end of a function is just like returning undefined, and that’s why the .value field of the result is undefined.

    Now might be a good time to go back to the talking cat demo page and really play around with the code. Try putting a yield inside a loop. What happens?

    In technical terms, each time a generator yields, its stack frame—the local variables, arguments, temporary values, and the current position of execution within the generator body—is removed from the stack. However, the Generator object keeps a reference to (or copy of) this stack frame, so that a later .next() call can reactivate it and continue execution.

    It’s worth pointing out that generators are not threads. In languages with threads, multiple pieces of code can run at the same time, usually leading to race conditions, nondeterminism, and sweet sweet performance. Generators are not like that at all. When a generator runs, it runs in the same thread as the caller. The order of execution is sequential and deterministic, and never concurrent. Unlike system threads, a generator is only ever suspended at points marked by yield in its body.

    All right. We know what generators are. We’ve seen a generator run, pause itself, then resume execution. Now for the big question. How could this weird ability possibly be useful?

    Generators are iterators

    Last week, we saw that ES6 iterators are not just a single built-in class. They’re an extension point of the language. You can create your own iterators just by implementing two methods: [Symbol.iterator]() and .next().

    But implementing an interface is always at least a little work. Let’s see what an iterator implementation looks like in practice. As an example, let’s make a simple range iterator that simply counts up from one number to another, like an old-fashioned C for (;;) loop.

    // This should "ding" three times
    for (var value of range(0, 3)) {
      alert("Ding! at floor #" + value);
    }
    

    Here’s one solution, using an ES6 class. (If the class syntax is not completely clear, don’t worry—we’ll cover it in a future blog post.)

    class RangeIterator {
      constructor(start, stop) {
        this.value = start;
        this.stop = stop;
      }
    
      [Symbol.iterator]() { return this; }
    
      next() {
        var value = this.value;
        if (value < this.stop) {
          this.value++;
          return {done: false, value: value};
        } else {
          return {done: true, value: undefined};
        }
      }
    }
    
    // Return a new iterator that counts up from 'start' to 'stop'.
    function range(start, stop) {
      return new RangeIterator(start, stop);
    }
    

    See this code in action.

    This is what implementing an iterator is like in Java or Swift. It’s not so bad. But it’s not exactly trivial either. Are there any bugs in this code? It’s not easy to say. It looks nothing like the original for (;;) loop we are trying to emulate here: the iterator protocol forces us to dismantle the loop.

    At this point you might be feeling a little lukewarm toward iterators. They may be great to use, but they seem hard to implement.

    It probably wouldn’t occur to you to suggest that we introduce a wild, mindbending new control flow structure to the JS language just to make iterators easier to build. But since we do have generators, can we use them here? Let’s try it:

    function* range(start, stop) {
      for (var i = start; i < stop; i++)
        yield i;
    }
    

    See this code in action.

    The above 4-line generator is a drop-in replacement for the previous 23-line implementation of range(), including the entire RangeIterator class. This is possible because generators are iterators. All generators have a built-in implementation of .next() and [Symbol.iterator](). You just write the looping behavior.

    Implementing iterators without generators is like being forced to write a long email entirely in the passive voice. When simply saying what you mean is not an option, what you end up saying instead can become quite convoluted. RangeIterator is long and weird because it has to describe the functionality of a loop without using loop syntax. Generators are the answer.

    How else can we use the ability of generators to act as iterators?

    • Making any object iterable. Just write a generator-function that traverses this, yielding each value as it goes. Then install that generator-function as the [Symbol.iterator] method of the object.

    • Simplifying array-building functions. Suppose you have a function that returns an array of results each time it’s called, like this one:

      // Divide the one-dimensional array 'icons'
      // into arrays of length 'rowLength'.
      function splitIntoRows(icons, rowLength) {
        var rows = [];
        for (var i = 0; i < icons.length; i += rowLength) {
          rows.push(icons.slice(i, i + rowLength));
        }
        return rows;
      }
      

      Generators make this kind of code a bit shorter:

      function* splitIntoRows(icons, rowLength) {
        for (var i = 0; i < icons.length; i += rowLength) {
          yield icons.slice(i, i + rowLength);
        }
      }
      

      The only difference in behavior is that instead of computing all the results at once and returning an array of them, this returns an iterator, and the results are computed one by one, on demand.

    • Results of unusual size. You can’t build an infinite array. But you can return a generator that generates an endless sequence, and each caller can draw from it however many values they need.

    • Refactoring complex loops. Do you have a huge ugly function? Would you like to break it into two simpler parts? Generators are a new knife to add to your refactoring toolkit. When you’re facing a complicated loop, you can factor out the part of the code that produces data, turning it into a separate generator-function. Then change the loop to say for (var data of myNewGenerator(args)).

    • Tools for working with iterables. ES6 does not provide an extensive library for filtering, mapping, and generally hacking on arbitrary iterable data sets. But generators are great for building the tools you need with just a few lines of code.

      For example, suppose you need an equivalent of Array.prototype.filter that works on DOM NodeLists, not just Arrays. Piece of cake:

      function* filter(test, iterable) {
        for (var item of iterable) {
          if (test(item))
            yield item;
        }
      }
      

    So are generators useful? Sure. They are an astonshingly easy way to implement custom iterators, and iterators are the new standard for data and loops throughout ES6.

    But that’s not all generators can do. It may not even turn out to be the most important thing they do.

    Generators and asynchronous code

    Here is some JS code I wrote a while back.

              };
            })
          });
        });
      });
    });
    

    Maybe you’ve seen something like this in your own code. Asynchronous APIs typically require a callback, which means writing an extra anonymous function every time you do something. So if you have a bit of code that does three things, rather than three lines of code, you’re looking at three indentation levels of code.

    Here is some more JS code I’ve written:

    }).on('close', function () {
      done(undefined, undefined);
    }).on('error', function (error) {
      done(error);
    });
    

    Asynchronous APIs have error-handling conventions rather than exceptions. Different APIs have different conventions. In most of them, errors are silently dropped by default. In some of them, even ordinary successful completion is dropped by default.

    Until now, these problems have simply been the price we pay for asynchronous programming. We have come to accept that asynchronous code just doesn’t look as nice and simple as the corresponding synchronous code.

    Generators offer new hope that it doesn’t have to be this way.

    Q.async() is an experimental attempt at using generators with promises to produce async code that resembles the corresponding synchronous code. For example:

    // Synchronous code to make some noise.
    function makeNoise() {
      shake();
      rattle();
      roll();
    }
    
    // Asynchronous code to make some noise.
    // Returns a Promise object that becomes resolved
    // when we're done making noise.
    function makeNoise_async() {
      return Q.async(function* () {
        yield shake_async();
        yield rattle_async();
        yield roll_async();
      });
    }
    

    The main difference is that the asynchronous version must add the yield keyword each place where it calls an asynchronous function.

    Adding a wrinkle like an if statement or a try/catch block in the Q.async version is exactly like adding it to the plain synchronous version. Compared to other ways of writing async code, this feels a lot less like learning a whole new language.

    If you’ve gotten this far, you might enjoy James Long’s very detailed post on this topic.

    So generators are pointing the way to a new asynchronous programming model that seems better suited to human brains. This work is ongoing. Among other things, better syntax might help. A proposal for async functions, building on both promises and generators, and taking inspiration from similar features in C#, is on the table for ES7.

    When can I use these crazy things?

    On the server, you can use ES6 generators today in io.js (and in Node if you use the --harmony command-line option).

    In the browser, only Firefox 27+ and Chrome 39+ support ES6 generators so far. To use generators on the web today, you’ll need to use Babel or Traceur to translate your ES6 code to Web-friendly ES5.

    A few shout-outs to deserving parties: Generators were first implemented in JS by Brendan Eich; his design closely followed Python generators which were inspired by Icon. They shipped in Firefox 2.0 back in 2006. The road to standardization was bumpy, and the syntax and behavior changed a bit along the way. ES6 generators were implemented in both Firefox and Chrome by compiler hacker Andy Wingo. This work was sponsored by Bloomberg.

    yield;

    There is more to say about generators. We didn’t cover the .throw() and .return() methods, the optional argument to .next(), or the yield* expression syntax. But I think this post is long and bewildering enough for now. Like generators themselves, we should pause, and take up the rest another time.

    But next week, let’s change gears a little. We’ve tackled two deep topics in a row here. Wouldn’t it be great to talk about an ES6 feature that won’t change your life? Something simple and obviously useful? Something that will make you smile? ES6 has a few of those too.

    Coming up: a feature that will plug right in to the kind of code you write every day. Please join us next week for a look at ES6 template strings in depth.

  10. ES6 In Depth: Iterators and the for-of loop

    ES6 In Depth is a series on new features being added to the JavaScript programming language in the 6th Edition of the ECMAScript standard, ES6 for short.

    How do you loop over the elements of an array? When JavaScript was introduced, twenty years ago, you would do it like this:

    for (var index = 0; index < myArray.length; index++) {
      console.log(myArray[index]);
    }
    

    Since ES5, you can use the built-in forEach method:

    myArray.forEach(function (value) {
      console.log(value);
    });
    

    This is a little shorter, but there is one minor drawback: you can’t break out of this loop using a break statement or return from the enclosing function using a return statement.

    It sure would be nice if there were just a for-loop syntax that looped over array elements.

    How about a forin loop?

    for (var index in myArray) {    // don't actually do this
      console.log(myArray[index]);
    }
    

    This is a bad idea for several reasons:

    • The values assigned to index in this code are the strings "0", "1", "2" and so on, not actual numbers. Since you probably don’t want string arithmetic ("2" + 1 == "21"), this is inconvenient at best.
    • The loop body will execute not only for array elements, but also for any other expando properties someone may have added. For example, if your array has an enumerable property myArray.name, then this loop will execute one extra time, with index == "name". Even properties on the array’s prototype chain can be visited.
    • Most astonishing of all, in some circumstances, this code can loop over the array elements in an arbitrary order.

    In short, forin was designed to work on plain old Objects with string keys. For Arrays, it’s not so great.

    The mighty for-of loop

    Remember last week I promised that ES6 would not break the JS code you’ve already written. Well, millions of Web sites depend on the behavior of forin—yes, even its behavior on arrays. So there was never any question of “fixing” forin to be more helpful when used with arrays. The only way for ES6 to improve matters was to add some kind of new loop syntax.

    And here it is:

    for (var value of myArray) {
      console.log(value);
    }
    

    Hmm. After all that build-up, it doesn’t seem all that impressive, does it? Well, we’ll see whether forof has any neat tricks up its sleeve. For now, just note that:

    • this is the most concise, direct syntax yet for looping through array elements
    • it avoids all the pitfalls of forin
    • unlike forEach(), it works with break, continue, and return

    The forin loop is for looping over object properties.

    The forof loop is for looping over data—like the values in an array.

    But that’s not all.

    Other collections support for-of too

    forof is not just for arrays. It also works on most array-like objects, like DOM NodeLists.

    It also works on strings, treating the string as a sequence of Unicode characters:

    for (var chr of "😺😲") {
      alert(chr);
    }
    

    It also works on Map and Set objects.

    Oh, I’m sorry. You’ve never heard of Map and Set objects? Well, they are new in ES6. We’ll do a whole post about them at some point. If you’ve worked with maps and sets in other languages, there won’t be any big surprises.

    For example, a Set object is good for eliminating duplicates:

    // make a set from an array of words
    var uniqueWords = new Set(words);
    

    Once you’ve got a Set, maybe you’d like to loop over its contents. Easy:

    for (var word of uniqueWords) {
      console.log(word);
    }
    

    A Map is slightly different: the data inside it is made of key-value pairs, so you’ll want to use destructuring to unpack the key and value into two separate variables:

    for (var [key, value] of phoneBookMap) {
      console.log(key + "'s phone number is: " + value);
    }
    

    Destructuring is yet another new ES6 feature and a great topic for a future blog post. I should write these down.

    By now, you get the picture: JS already has quite a few different collection classes, and even more are on the way. forof is designed to be the workhorse loop statement you use with all of them.

    forof does not work with plain old Objects, but if you want to iterate over an object’s properties you can either use forin (that’s what it’s for) or the builtin Object.keys():

    // dump an object's own enumerable properties to the console
    for (var key of Object.keys(someObject)) {
      console.log(key + ": " + someObject[key]);
    }
    

    Under the hood

    “Good artists copy, great artists steal.” —Pablo Picasso

    A running theme in ES6 is that the new features being added to the language didn’t come out of nowhere. Most have been tried and proven useful in other languages.

    The forof loop, for example, resembles similar loop statements in C++, Java, C#, and Python. Like them, it works with several different data structures provided by the language and its standard library. But it’s also an extension point in the language.

    Like the for/foreach statements in those other languages, forof works entirely in terms of method calls. What Arrays, Maps, Sets, and the other objects we talked about all have in common is that they have an iterator method.

    And there’s another kind of object that can have an iterator method too: any object you want.

    Just as you can add a myObject.toString() method to any object and suddenly JS knows how to convert that object to a string, you can add the myObject[Symbol.iterator]() method to any object and suddenly JS will know how to loop over that object.

    For example, suppose you’re using jQuery, and although you’re very fond of .each(), you would like jQuery objects to work with forof as well. Here’s how to do that:

    // Since jQuery objects are array-like,
    // give them the same iterator method Arrays have
    jQuery.prototype[Symbol.iterator] =
      Array.prototype[Symbol.iterator];
    

    OK, I know what you’re thinking. That [Symbol.iterator] syntax seems weird. What is going on there? It has to do with the method’s name. The standard committee could have just called this method .iterator(), but then, your existing code might already have some objects with .iterator() methods, and that could get pretty confusing. So the standard uses a symbol, rather than a string, as the name of this method.

    Symbols are new in ES6, and we’ll tell you all about them in—you guessed it—a future blog post. For now, all you need to know is that the standard can define a brand-new symbol, like Symbol.iterator, and it’s guaranteed not to conflict with any existing code. The trade-off is that the syntax is a little weird. But it’s a small price to pay for this versatile new feature and excellent backward compatibility.

    An object that has a [Symbol.iterator]() method is called iterable. In coming weeks, we’ll see that the concept of iterable objects is used throughout the language, not only in forof but in the Map and Set constructors, destructuring assignment, and the new spread operator.

    Iterator objects

    Now, there is a chance you will never have to implement an iterator object of your own from scratch. We’ll see why next week. But for completeness, let’s look at what an iterator object looks like. (If you skip this whole section, you’ll mainly be missing crunchy technical details.)

    A forof loop starts by calling the [Symbol.iterator]() method on the collection. This returns a new iterator object. An iterator object can be any object with a .next() method; the forof loop will call this method repeatedly, once each time through the loop. For example, here’s the simplest iterator object I can think of:

    var zeroesForeverIterator = {
      [Symbol.iterator]: function () {
        return this;
      },
      next: function () {
        return {done: false, value: 0};
      }
    };
    

    Every time this .next() method is called, it returns the same result, telling the forof loop (a) we’re not done iterating yet; and (b) the next value is 0. This means that for (value of zeroesForeverIterator) {} will be an infinite loop. Of course, a typical iterator will not be quite this trivial.

    This iterator design, with its .done and .value properties, is superficially different from how iterators work in other languages. In Java, iterators have separate .hasNext() and .next() methods. In Python, they have a single .next() method that throws StopIteration when there are no more values. But all three designs are fundamentally returning the same information.

    An iterator object can also implement optional .return() and .throw(exc) methods. The forof loop calls .return() if the loop exits prematurely, due to an exception or a break or return statement. The iterator can implement .return() if it needs to do some cleanup or free up resources it was using. Most iterator objects won’t need to implement it. .throw(exc) is even more of a special case: forof never calls it at all. But we’ll hear more about it next week.

    Now that we have all the details, we can take a simple forof loop and rewrite it in terms of the underlying method calls.

    First the forof loop:

    for (VAR of ITERABLE) {
      STATEMENTS
    }
    

    Here is a rough equivalent, using the underlying methods and a few temporary variables:

    var $iterator = ITERABLE[Symbol.iterator]();
    var $result = $iterator.next();
    while (!$result.done) {
      VAR = $result.value;
      STATEMENTS
      $result = $iterator.next();
    }
    

    This code doesn’t show how .return() is handled. We could add that, but I think it would obscure what’s going on rather than illuminate it. forof is easy to use, but there is a lot going on behind the scenes.

    When can I start using this?

    The forof loop is supported in all current Firefox releases. It’s supported in Chrome if you go to chrome://flags and enable “Experimental JavaScript”. It also works in Microsoft’s Spartan browser, but not in shipping versions of IE. If you’d like to use this new syntax on the web, but you need to support IE and Safari, you can use a compiler like Babel or Google’s Traceur to translate your ES6 code to Web-friendly ES5.

    On the server, you don’t need a compiler—you can start using forof in io.js (and Node, with the --harmony option) today.

    (UPDATE: This previously neglected to mention that forof is disabled by default in Chrome. Thanks to Oleg for pointing out the mistake in the comments.)

    {done: true}

    Whew!

    Well, we’re done for today, but we’re still not done with the forof loop.

    There is one more new kind of object in ES6 that works beautifully with forof. I didn’t mention it because it’s the topic of next week’s post. I think this new feature is the most magical thing in ES6. If you haven’t already encountered it in languages like Python and C#, you’ll probably find it mind-boggling at first. But it’s the easiest way to write an iterator, it’s useful in refactoring, and it might just change the way we write asynchronous code, both in the browser and on the server. So join us next week as we look at ES6 generators in depth.