Mozilla

JavaScript Articles

Sort by:

View:

  1. ES6 In Depth: let and const

    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.

    The feature I’d like to talk about today is at once humble and startlingly ambitious.

    When Brendan Eich designed the first version of JavaScript back in 1995, he got plenty of things wrong, including things that have been part of the language ever since, like the Date object and objects automatically converting to NaN when you accidentally multiply them. However, the things he got right are stunningly important things, in hindsight: objects; prototypes; first-class functions with lexical scoping; mutability by default. The language has good bones. It was better than anyone realized at first.

    Still, Brendan made one particular design decision that bears on today’s article—a decision that I think can be fairly characterized as a mistake. It’s a little thing. A subtle thing. You might use the language for years and not even notice it. But it matters, because this mistake is in the side of the language that we now think of as “the good parts”.

    It has to do with variables.

    Problem #1: Blocks are not scopes

    The rule sounds so innocent: The scope of a var declared in a JS function is the whole body of that function. But there are two ways this can have groan-inducing consequences.

    One is that the scope of variables declared in blocks is not just the block. It’s the entire function.

    You may never have noticed this before. I’m afraid it’s one of those things you won’t be able to un-see. Let’s walk through a scenario where it leads to a tricky bug.

    Say you have some existing code that uses a variable named t:

    function runTowerExperiment(tower, startTime) {
      var t = startTime;
    
      tower.on("tick", function () {
        ... code that uses t ...
      });
      ... more code ...
    }
    

    Everything works great, so far. Now you want to add bowling ball speed measurements, so you add a little if-statement to the inner callback function.

    function runTowerExperiment(tower, startTime) {
      var t = startTime;
    
      tower.on("tick", function () {
        ... code that uses t ...
        if (bowlingBall.altitude() <= 0) {
          var t = readTachymeter();
          ...
        }
      });
      ... more code ...
    }
    

    Oh, dear. You’ve unwittingly added a second variable named t. Now, in the “code that uses t”, which was working fine before, t refers to the new inner variable t rather than the existing outer variable.

    The scope of a var in JavaScript is like the bucket-of-paint tool in Photoshop. It extends in both directions from the declaration, forwards and backwards, and it just keeps going until it reaches a function boundary. Since this variable t’s scope extends so far backwards, it has to be created as soon as we enter the function. This is called hoisting. I like to imagine the JS engine lifting each var and function to the top of the enclosing function with a tiny code crane.

    Now, hoisting has its good points. Without it, lots of perfectly cromulent techniques that work fine in the global scope wouldn’t work inside an IIFE. But in this case, hoisting is causing a nasty bug: all your calculations using t will start producing NaN. It’ll be hard to track down, too, especially if your code is larger than this toy example.

    Adding a new block of code caused a mysterious error in code before that block. Is it just me, or is that really weird? We don’t expect effects to precede causes.

    But this is a piece of cake compared to the second var problem.

    Problem #2: Variable oversharing in loops

    You can guess what happens when you run this code. It’s totally straightforward:

    var messages = ["Hi!", "I'm a web page!", "alert() is fun!"];
    
    for (var i = 0; i < messages.length; i++) {
      alert(messages[i]);
    }
    

    If you’ve been following this series, you know I like to use alert() for example code. Maybe you also know that alert() is a terrible API. It’s synchronous. So while an alert is visible, input events are not delivered. Your JS code—and in fact your whole UI—is basically paused until the user clicks OK.

    All of which makes alert() the wrong choice for almost anything you want to do in a web page. I use it because I think all those same things make alert() a great teaching tool.

    Still, I could be persuaded to give up all that clunkiness and bad behavior… if it means I can make a talking cat.

    var messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];
    
    for (var i = 0; i < messages.length; i++) {
      setTimeout(function () {
        cat.say(messages[i]);
      }, i * 1500);
    }
    

    See this code working incorrectly in action!

    But something’s wrong. Instead of saying all three messages in order, the cat says “undefined” three times.

    Can you spot the bug?

    (Photo of a caterpillar well camouflaged on the bark of a tree. Gujarat, India.)

    Photo credit: nevil saveri

    The problem here is that there is only one variable i. It’s shared by the loop itself and all three timeout callbacks. When the loop finishes running, the value of i is 3 (because messages.length is 3), and none of the callbacks have been called yet.

    So when the first timeout fires, and calls cat.say(messages[i]), it’s using messages[3]. Which of course is undefined.

    There are many ways to fix this (here’s one), but this is a second problem caused by the var scoping rules. It would be awfully nice never to have this kind of problem in the first place.

    let is the new var

    For the most part, design mistakes in JavaScript (other programming languages too, but especially JavaScript) can’t be fixed. Backwards compatibility means never changing the behavior of existing JS code on the Web. Even the standard committee has no power to, say, fix the weird quirks in JavaScript’s automatic semicolon insertion. Browser makers simply will not implement breaking changes, because that kind of change punishes their users.

    So about ten years ago, when Brendan Eich decided to fix this problem, there was really only one way to do it.

    He added a new keyword, let, that could be used to declare variables, just like var, but with better scoping rules.

    It looks like this:

    let t = readTachymeter();
    

    Or this:

    for (let i = 0; i < messages.length; i++) {
      ...
    }
    

    let and var are different, so if you just do a global search-and-replace throughout your code, that could break parts of your code that (probably unintentionally) depend on the quirks of var. But for the most part, in new ES6 code, you should just stop using var and use let everywhere instead. Hence the slogan: “let is the new var”.

    What exactly are the differences between let and var? Glad you asked!

    • let variables are block-scoped. The scope of a variable declared with let is just the enclosing block, not the whole enclosing function.

      There’s still hoisting with let, but it’s not as indiscriminate. The runTowerExperiment example can be fixed simply by changing var to let. If you use let everywhere, you will never have that kind of bug.

    • Global let variables are not properties on the global object. That is, you won’t access them by writing window.variableName. Instead, they live in the scope of an invisible block that notionally encloses all JS code that runs in a web page.

    • Loops of the form for (let x...) create a fresh binding for x in each iteration.

      This is a very subtle difference. It means that if a for (let...) loop executes multiple times, and that loop contains a closure, as in our talking cat example, each closure will capture a different copy of the loop variable, rather than all closures capturing the same loop variable.

      So the talking cat example, too, can be fixed just by changing var to let.

      This applies to all three kinds of for loop: forof, forin, and the old-school C kind with semicolons.

    • It’s an error to try to use a let variable before its declaration is reached. The variable is uninitialized until control flow reaches the line of code where it’s declared. For example:

      function update() {
        console.log("current time:", t);  // ReferenceError
        ...
        let t = readTachymeter();
      }
      

      This rule is there to help you catch bugs. Instead of NaN results, you’ll get an exception on the line of code where the problem is.

      This period when the variable is in scope, but uninitialized, is called the temporal dead zone. I keep waiting for this inspired bit of jargon to make the leap to science fiction. Nothing yet.

      (Crunchy performance details: In most cases, you can tell whether the declaration has run or not just by looking at the code, so the JavaScript engine does not actually need to perform an extra check every time the variable is accessed to make sure it’s been initialized. However, inside a closure, it sometimes isn’t clear. In those cases the JavaScript engine will do a run-time check. That means let can be a touch slower than var.)

      (Crunchy alternate-universe scoping details: In some programming languages, the scope of a variable starts at the point of the declaration, instead of reaching backwards to cover the whole enclosing block. The standard committee considered using that kind of scoping rule for let. That way, the use of t that causes a ReferenceError here simply wouldn’t be in the scope of the later let t, so it wouldn’t refer to that variable at all. It could refer to a t in an enclosing scope. But this approach did not work well with closures or with function hoisting, so it was eventually abandoned.)

    • Redeclaring a variable with let is a SyntaxError.

      This rule, too, is there to help you detect trivial mistakes. Still, this is the difference that is most likely to cause you some issues if you attempt a global let-to-var conversion, because it applies even to global let variables.

      If you have several scripts that all declare the same global variable, you’d better keep using var for that. If you switch to let, whichever script loads second will fail with an error.

      Or use ES6 modules. But that’s a story for another day.

    (Crunchy syntax details: let is a reserved word in strict mode code. In non-strict-mode code, for the sake of backward compatibility, you can still declare variables, functions, and arguments named let—you can write var let = 'q';! Not that you would do that. And let let; is not allowed at all.)

    Apart from those differences, let and var are pretty much the same. They both support declaring multiple variables separated by commas, for example, and they both support destructuring.

    Note that class declarations behave like let, not var. If you load a script containing a class multiple times, the second time you’ll get an error for redeclaring the class.

    const

    Right, one more thing!

    ES6 also introduces a third keyword that you can use alongside let: const.

    Variables declared with const are just like let except that you can’t assign to them, except at the point where they’re declared. It’s a SyntaxError.

    const MAX_CAT_SIZE_KG = 3000; // 🙀
    
    MAX_CAT_SIZE_KG = 5000; // SyntaxError
    MAX_CAT_SIZE_KG++; // nice try, but still a SyntaxError
    

    Sensibly enough, you can’t declare a const without giving it a value.

    const theFairest;  // SyntaxError, you troublemaker
    

    Secret agent namespace

    “Namespaces are one honking great idea—let’s do more of those!” —Tim Peters, “The Zen of Python”

    Behind the scenes, nested scopes are one of the core concepts that programming languages are built around. It’s been this way since what, ALGOL? Something like 57 years. And it’s truer today than ever.

    Before ES3, JavaScript only had global scopes and function scopes. (Let’s ignore with statements.) ES3 introduced trycatch statements, which meant adding a new kind of scope, used only for the exception variable in catch blocks. ES5 added a scope used by strict eval(). ES6 adds block scopes, for-loop scopes, the new global let scope, module scopes, and additional scopes that are used when evaluating default values for arguments.

    All the extra scopes added from ES3 onward are necessary to make JavaScript’s procedural and object-oriented features work as smoothly, precisely, and intuitively as closures—and cooperate seamlessly with closures. Maybe you never noticed any of these scoping rules before today. If so, the language is doing its job.

    Can I use let and const now?

    Yes. To use them on the web, you’ll have to use an ES6 compiler such as Babel, Traceur, or TypeScript. (Babel and Traceur do not support the temporal dead zone yet.)

    io.js supports let and const, but only in strict-mode code. Node.js support is the same, but the --harmony option is also required.

    Brendan Eich implemented the first version of let in Firefox nine years ago. The feature was thoroughly redesigned during the standardization process. Shu-yu Guo is upgrading our implementation to match the standard, with code reviews by Jeff Walden and others.

    Well, we’re in the home stretch. The end of our epic tour of ES6 features is in sight. In two weeks, we’ll finish up with what’s probably the most eagerly awaited ES6 feature of them all. But first, next week we’ll have a post that extends our earlier coverage of a new feature that’s just super. So please join us as Eric Faust returns with a look at ES6 subclassing in depth.

  2. ES6 In Depth: Classes

    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, we get a bit of a respite from the complexity that we’ve seen in previous posts in this series. There are no new never-before-seen ways of writing code with Generators; no all-powerful Proxy objects which provide hooks into the inner algorithmic workings of the JavaScript language; no new data structures that obviate the need for roll-your-own solutions. Instead, we get to talk about syntactic and idiomatic cleanups for an old problem: object constructor creation in JavaScript.

    The Problem

    Say we want to create the most quintessential example of object-oriented design principles: the Circle class. Imagine we are writing a Circle for a simple Canvas library. Among other things, we might want to know how to do the following:

    • Draw a given Circle to a given Canvas.
    • Keep track of the total number of Circles ever made.
    • Keep track of the radius of a given Circle, and how to enforce invariants on its value.
    • Calculate the area of a given Circle.

    Current JS idioms say that we should first create the constructor as a function, then add any properties we might want to the function itself, then replace the prototype property of that constructor with an object. This prototype object will contain all of the properties that instance objects created by our constructor should start with. For even a simple example, by the time you get it all typed out, this ends up being a lot of boilerplate:

    function Circle(radius) {
        this.radius = radius;
        Circle.circlesMade++;
    }
    
    Circle.draw = function draw(circle, canvas) { /* Canvas drawing code */ }
    
    Object.defineProperty(Circle, "circlesMade", {
        get: function() {
            return !this._count ? 0 : this._count;
        },
    
        set: function(val) {
            this._count = val;
        }
    });
    
    Circle.prototype = {
        area: function area() {
            return Math.pow(this.radius, 2) * Math.PI;
        }
    };
    
    Object.defineProperty(Circle.prototype, "radius", {
        get: function() {
            return this._radius;
        },
    
        set: function(radius) {
            if (!Number.isInteger(radius))
                throw new Error("Circle radius must be an integer.");
            this._radius = radius;
        }
    });
    

    Not only is the code cumbersome, it’s also far from intuitive. It requires having a non-trivial understanding of the way functions work, and how various installed properties make their way onto created instance objects. If this approach seems complicated, don’t worry. The whole point of this post is to show off a much simpler way of writing code that does all of this.

    Method Definition Syntax

    In a first attempt to clean this up, ES6 offered a new syntax for adding special properties to an object. While it was easy to add the area method to Circle.prototype above, it felt much heavier to add the getter/setter pair for radius. As JS moved towards a more object-oriented approach, people became interested in designing cleaner ways to add accessors to objects. We needed a new way of adding “methods” to an object exactly as if they had been added with obj.prop = method, without the weight of Object.defineProperty. People wanted to be able to do the following things easily:

    1. Add normal function properties to an object.
    2. Add generator function properties to an object.
    3. Add normal accessor function properties to an object.
    4. Add any of the above as if you had done it with [] syntax on the finished object. We’ll call these Computed property names.

    Some of these things couldn’t be done before. For example, there is no way to define a getter or setter with assignments to obj.prop. Accordingly, new syntax had to be added. You can now write code that looks like this:

    var obj = {
        // Methods are now added without a function keyword, using the name of the
        // property as the name of the function.
        method(args) { ... },
    
        // To make a method that's a generator instead, just add a '*', as normal.
        *genMethod(args) { ... },
    
        // Accessors can now go inline, with the help of |get| and |set|. You can
        // just define the functions inline. No generators, though.
    
        // Note that a getter installed this way must have no arguments
        get propName() { ... },
    
        // Note that a setter installed this way must have exactly one argument
        set propName(arg) { ... },
    
        // To handle case (4) above, [] syntax is now allowed anywhere a name would
        // have gone! This can use symbols, call functions, concatenate strings, or
        // any other expression that evaluates to a property id. Though I've shown
        // it here as a method, this syntax also works for accessors or generators.
        [functionThatReturnsPropertyName()] (args) { ... }
    };
    

    Using this new syntax, we can now rewrite our snippet above:

    function Circle(radius) {
        this.radius = radius;
        Circle.circlesMade++;
    }
    
    Circle.draw = function draw(circle, canvas) { /* Canvas drawing code */ }
    
    Object.defineProperty(Circle, "circlesMade", {
        get: function() {
            return !this._count ? 0 : this._count;
        },
    
        set: function(val) {
            this._count = val;
        }
    });
    
    Circle.prototype = {
        area() {
            return Math.pow(this.radius, 2) * Math.PI;
        },
    
        get radius() {
            return this._radius;
        },
        set radius(radius) {
            if (!Number.isInteger(radius))
                throw new Error("Circle radius must be an integer.");
            this._radius = radius;
        }
    };
    

    Pedantically, this code isn’t exactly identical to the snippet above. Method definitions in object literals are installed as configurable and enumerable, while the accessors installed in the first snippet will be non-configurable and non-enumerable. In practice, this is rarely noticed, and I decided to elide enumerability and configurability above for brevity.

    Still, it’s getting better, right? Unfortunately, even armed with this new method definition syntax, there’s not much we can do for the definition of Circle, as we have yet to define the function. There’s no way to get properties onto a function as you’re defining it.

    Class Definition Syntax

    Though this was better, it still didn’t satisfy people who wanted a cleaner solution to object-oriented design in JavaScript. Other languages have a construct for handling object-oriented design, they argued, and that construct is called a class.

    Fair enough. Let’s add classes, then.

    We want a system that will allow us to add methods to a named constructor, and add methods to its .prototype as well, so that they will appear on constructed instances of the class. Since we have our fancy new method definition syntax, we should definitely use it. Then, we only need a way to dfferentiate between what is generalized over all instances of the class, and what functions are specific to a given instance. In C++ or Java, the keyword for that is static. Seems as good as any. Let’s use it.

    Now it would be useful to have a way to designate one of the methods of the bunch to be the function that gets called as the constructor. In C++ or Java, that would be named the same as the class, with no return type. Since JS doesn’t have return types, and we need a .constructor property anyway, for backwards compatibility, let’s call that method constructor.

    Putting it together, we can rewrite our Circle class as it was always meant to be:

    class Circle {
        constructor(radius) {
            this.radius = radius;
            Circle.circlesMade++;
        };
    
        static draw(circle, canvas) {
            // Canvas drawing code
        };
    
        static get circlesMade() {
            return !this._count ? 0 : this._count;
        };
        static set circlesMade(val) {
            this._count = val;
        };
    
        area() {
            return Math.pow(this.radius, 2) * Math.PI;
        };
    
        get radius() {
            return this._radius;
        };
        set radius(radius) {
            if (!Number.isInteger(radius))
                throw new Error("Circle radius must be an integer.");
            this._radius = radius;
        };
    }
    

    Wow! Not only can we group everything related to a Circle together, but everything looks so… clean. This is definitely better than what we started with.

    Even so, some of you are likely to have questions or to find edge cases. I’ll try to anticipate and address some of these below:

    • What’s with the semicolons? – In an attempt to “make things look more like traditional classes,” we decided to go with a more traditional separator. Don’t like it? It’s optional. No delimiter is required.

    • What if I don’t want a constructor, but still want to put methods on created objects? – That’s fine. The constructor method is totally optional. If you don’t supply one, the default is as if you had typed constructor() {}.

    • Can constructor be a generator? – Nope! Adding a constructor that’s not a normal method will result in a TypeError. This includes both generators and accessors.

    • Can I define constructor with a computed property name? – Unfortunately not. That would be really hard to detect, so we don’t try. If you define a method with a computed property name that ends up being named constructor, you will still get a method named constructor, it just won’t be the class’s constructor function.

    • What if I change the value of Circle? Will that cause new Circle to misbehave? – Nope! Much like function expressions, classes get an internal binding of their given name. This binding cannot be changed by external forces, so no matter what you set the Circle variable to in the enclosing scope, Circle.circlesMade++ in the constructor will function as expected.

    • OK, but I could pass an object literal directly as a function argument. This new class thing looks like it won’t work anymore. – Luckily, ES6 also adds class expressions! They can be either named or unnamed, and will behave exactly the same way as described above, except they won’t create a variable in the scope in which you declare them.

    • What about those shenanigans above with enumerability and so on? – People wanted to make it so that you could install methods on objects, but that when you enumerated the object’s properties, you only got the added data properties of the object. Makes sense. Because of this, installed methods in classes are configurable, but not enumerable.

    • Hey, wait… what..? Where are my instance variables? What about static constants? – You caught me. They currently don’t exist in class definitions in ES6. Good news, though! Along with others involved in the spec process, I am a strong proponent of both static and const values being installable in class syntax. In fact, it’s already come up in spec meetings! I think we can look forward to more discussion of this in the future.

    • OK, even still, these are awesome! Can I use them yet? – Not exactly. There are polyfill options (especially Babel) so that you can play around with them today. Unfortunately, it’s going to be a little while before they are natively implemented in all major browsers. I’ve implemented everything we discussed here today in the Nightly version of Firefox, and it’s implemented but not enabled by default in Edge and Chrome. Unfortunately, it looks like there’s no current implementation in Safari.

    • Java and C++ have subclassing and a super keyword, but there’s nothing mentioned here. Does JS have that? – It does! However, that’s a whole other post’s worth of discussion. Check back with us later for an update about subclassing, where we’ll discuss more about the power of JavaScript classes.

    I would not have been able to implement classes without the guidance and enormous code review responsiblity of Jason Orendorff and Jeff Walden.

    Next week, Jason Orendorff returns from a week’s vacation and takes up the subject of let and const.

  3. ES6 In Depth: Proxies

    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.

    Here is the sort of thing we are going to do today.

    var obj = new Proxy({}, {
      get: function (target, key, receiver) {
        console.log(`getting ${key}!`);
        return Reflect.get(target, key, receiver);
      },
      set: function (target, key, value, receiver) {
        console.log(`setting ${key}!`);
        return Reflect.set(target, key, value, receiver);
      }
    });
    

    That’s a little complicated for a first example. I’ll explain all the parts later. For now, check out the object we created:

    > obj.count = 1;
        setting count!
    > ++obj.count;
        getting count!
        setting count!
        2
    

    What’s going on here? We are intercepting property accesses on this object. We are overloading the "." operator.

    How it’s done

    The best trick in computing is called virtualization. It’s a very general-purpose technique for doing astonishing things. Here’s how it works.

    1. Take any picture.

      (picture of a coal power plant)

      Photo credit: Martin Nikolaj Bech
    2. Draw an outline around something in the picture.

      (same photo, with the power plant circled)
    3. Now replace either everything inside the outline, or everything outside the outline, with something totally unexpected. There is just one rule, the Rule of Backwards Compatibility. Your replacement must behave enough like what was there before that nobody on the other side of the line notices that anything has changed.

      (the circled part is replaced with a wind farm)

      Photo credit: Beverley Goodwin.

    You’ll be familiar with this kind of hack from classic computer science films such as The Truman Show and The Matrix, where a person is inside the outline, and the rest of the world has been replaced with an elaborate illusion of normalcy.

    In order to satisfy the Rule of Backwards Compatibility, your replacement may need to be cunningly designed. But the real trick is in drawing the right outline.

    By outline, I mean an API boundary. An interface. Interfaces specify how two bits of code interact and what each part expects of the other. So if an interface is designed into the system, the outline is already drawn for you. You know you can replace either side, and the other side won’t care.

    It’s when there’s not an existing interface that you have to get creative. Some of the coolest software hacks of all time have involved drawing an API boundary where previously there was none, and bringing that interface into existence via a prodigious engineering effort.

    Virtual memory, Hardware virtualization, Docker, Valgrind, rr—to various degrees all of these projects involved driving new and rather unexpected interfaces into existing systems. In some cases, it took years and new operating system features and even new hardware to make the new boundary work well.

    The best virtualization hacks bring with them a new understanding of whatever’s being virtualized. To write an API for something, you have to understand it. Once you understand, you can do amazing things.

    ES6 introduces virtualization support for JavaScript’s most fundamental concept: the object.

    What is an object?

    No, really. Take a moment. Think it over. Scroll down when you know what an object is.

    (picture of Auguste Rodin’s sculpture, The Thinker)

    Photo credit: Joe deSousa.

    This question is too hard for me! I’ve never heard a really satisfying definition.

    Is that surprising? Defining fundamental concepts is always hard—check out the first few definitions in Euclid’s Elements sometime. The ECMAScript language specification is in good company, therefore, when it unhelpfully defines an object as a “member of the type Object.”

    Later, the spec adds that “An Object is a collection of properties.” That’s not bad. If you want a definition, that will do for now. We’ll come back to it later.

    I said before that to write an API for something, you have to understand it. So in a way, I’ve promised that if we get through all this, we’re going to understand objects better, and we’ll be able to do amazing things.

    So let’s follow in the footsteps of the ECMAScript standard committee and see what it would take to define an API, an interface, for JavaScript objects. What sort of methods do we need? What can objects do?

    That depends somewhat on the object. DOM Element objects can do certain things; AudioNode objects do other things. But there are a few fundamental abilities all objects share:

    • Objects have properties. You can get and set properties, delete them, and so on.
    • Objects have prototypes. This is how inheritance works in JS.
    • Some objects are functions or constructors. You can call them.

    Almost everything JS programs do with objects is done using properties, prototypes, and functions. Even the special behavior of an Element or AudioNode object is accessed by calling methods, which are just inherited function properties.

    So when the ECMAScript standard committee defined a set of 14 internal methods, the common interface for all objects, it should come as no surprise that they ended up focusing on these three fundamental things.

    The full list can be found in tables 5 and 6 of the ES6 standard. Here I’ll just describe a few. The weird double brackets, [[ ]], emphasize that these are internal methods, hidden from ordinary JS code. You can’t call, delete, or overwrite these like ordinary methods.

    • obj.[[Get]](key, receiver) – Get the value of a property.

      Called when JS code does: obj.prop or obj[key].

      obj is the object currently being searched; receiver is the object where we first started searching for this property. Sometimes we have to search several objects. obj might be an object on receiver’s prototype chain.

    • obj.[[Set]](key, value, receiver) – Assign to a property of an object.

      Called when JS code does: obj.prop = value or obj[key] = value.

      In an assignment like obj.prop += 2, the [[Get]] method is called first, and the [[Set]] method afterwards. Same goes for ++ and --.

    • obj.[[HasProperty]](key) – Test whether a property exists.

      Called when JS code does: key in obj.

    • obj.[[Enumerate]]() – List obj’s enumerable properties.

      Called when JS code does: for (key in obj) ....

      This returns an iterator object, and that’s how a forin loop gets an object’s property names.

    • obj.[[GetPrototypeOf]]() – Return obj’s prototype.

      Called when JS code does: obj.__proto__ or Object.getPrototypeOf(obj).

    • functionObj.[[Call]](thisValue, arguments) – Call a function.

      Called when JS code does: functionObj() or x.method().

      Optional. Not every object is a function.

    • constructorObj.[[Construct]](arguments, newTarget) – Invoke a constructor.

      Called when JS code does: new Date(2890, 6, 2), for example.

      Optional. Not every object is a constructor.

      The newTarget argument plays a role in subclassing. We’ll cover it in a future post.

    Maybe you can guess at some of the other seven.

    Throughout the ES6 standard, wherever possible, any bit of syntax or builtin function that does anything with objects is specified in terms of the 14 internal methods. ES6 drew a clear boundary around the brains of an object. What proxies let you do is replace the standard kind of brains with arbitrary JS code.

    When we start talking about overriding these internal methods in a moment, remember, we’re talking about overriding the behavior of core syntax like obj.prop, builtin functions like Object.keys(), and more.

    Proxy

    ES6 defines a new global constructor, Proxy. It takes two arguments: a target object and a handler object. So a simple example would look like this:

    var target = {}, handler = {};
    var proxy = new Proxy(target, handler);
    

    Let’s set aside the handler object for a moment and focus on how proxy and target are related.

    I can tell you how proxy is going to behave in one sentence. All of proxy’s internal methods are forwarded to target. That is, if something calls proxy.[[Enumerate]](), it’ll just return target.[[Enumerate]]().

    Let’s try it out. We’ll do something that causes proxy.[[Set]]() to be called.

    proxy.color = "pink";
    

    OK, what just happened? proxy.[[Set]]() should have called target.[[Set]](), so that should have made a new property on target. Did it?

    > target.color
        "pink"
    

    It did. And the same goes for all the other internal methods. This proxy will, for the most part, behave exactly the same as its target.

    There are limits to the fidelity of the illusion. You’ll find that proxy !== target. And a proxy will sometimes flunk type checks that the target would pass. Even if a proxy’s target is a DOM Element, for example, the proxy isn’t really an Element; so something like document.body.appendChild(proxy) will fail with a TypeError.

    Proxy handlers

    Now let’s return to the handler object. This is what makes proxies useful.

    The handler object’s methods can override any of the proxy’s internal methods.

    For example, if you’d like to intercept all attempts to assign to an object’s properties, you can do that by defining a handler.set() method:

    var target = {};
    var handler = {
      set: function (target, key, value, receiver) {
        throw new Error("Please don't set properties on this object.");
      }
    };
    var proxy = new Proxy(target, handler);
    
    > proxy.name = "angelina";
        Error: Please don't set properties on this object.
    

    The full list of handler methods is documented on the MDN page for Proxy. There are 14 methods, and they line up with the 14 internal methods defined in ES6.

    All handler methods are optional. If an internal method is not intercepted by the handler, then it’s forwarded to the target, as we saw before.

    Example: “Impossible” auto-populating objects

    We now know enough about proxies to try using them for something really weird, something that’s impossible without proxies.

    Here’s our first exercise. Make a function Tree() that can do this:

    > var tree = Tree();
    > tree
        { }
    > tree.branch1.branch2.twig = "green";
    > tree
        { branch1: { branch2: { twig: "green" } } }
    > tree.branch1.branch3.twig = "yellow";
        { branch1: { branch2: { twig: "green" },
                     branch3: { twig: "yellow" }}}
    

    Note how all the intermediate objects branch1, branch2, and branch3, are magically autocreated when they’re needed. Convenient, right? How could it possibly work?

    Until now, there’s no way it could work. But with proxies this is only a few lines of code. We just need to tap into tree.[[Get]](). If you like a challenge, you might want to try implementing this yourself before reading on.

    (picture of a tap in a maple tree)

    Not the right way to tap into a tree in JS. Photo credit: Chiot’s Run.

    Here’s my solution:

    function Tree() {
      return new Proxy({}, handler);
    }
    
    var handler = {
      get: function (target, key, receiver) {
        if (!(key in target)) {
          target[key] = Tree();  // auto-create a sub-Tree
        }
        return Reflect.get(target, key, receiver);
      }
    };
    

    Note the call to Reflect.get() at the end. It turns out there’s an extremely common need, in proxy handler methods, to be able to say “now just do the default behavior of delegating to target.” So ES6 defines a new Reflect object with 14 methods on it that you can use to do exactly that.

    Example: A read-only view

    I think I may have given the false impression that proxies are easy to use. Let’s do one more example to see if that’s true.

    This time our assignment is more complex: we have to implement a function, readOnlyView(object), that takes any object and returns a proxy that behaves just like that object, except without the ability to mutate it. So, for example, it should behave like this:

    > var newMath = readOnlyView(Math);
    > newMath.min(54, 40);
        40
    > newMath.max = Math.min;
        Error: can't modify read-only view
    > delete newMath.sin;
        Error: can't modify read-only view
    

    How can we implement this?

    The first step is to intercept all internal methods that would modify the target object if we let them through. There are five of those.

    function NOPE() {
      throw new Error("can't modify read-only view");
    }
    
    var handler = {
      // Override all five mutating methods.
      set: NOPE,
      defineProperty: NOPE,
      deleteProperty: NOPE,
      preventExtensions: NOPE,
      setPrototypeOf: NOPE
    };
    
    function readOnlyView(target) {
      return new Proxy(target, handler);
    }
    

    This works. It prevents assignment, property definition, and so on via the read-only view.

    Are there any loopholes in this scheme?

    The biggest problem is that the [[Get]] method, and others, may still return mutable objects. So even if some object x is a read-only view, x.prop may be mutable! That’s a huge hole.

    To plug it, we must add a handler.get() method:

    var handler = {
      ...
    
      // Wrap other results in read-only views.
      get: function (target, key, receiver) {
        // Start by just doing the default behavior.
        var result = Reflect.get(target, key, receiver);
    
        // Make sure not to return a mutable object!
        if (Object(result) === result) {
          // result is an object.
          return readOnlyView(result);
        }
        // result is a primitive, so already immutable.
        return result;
      },
    
      ...
    };
    

    This is not sufficient either. Similar code is needed for other methods, including getPrototypeOf and getOwnPropertyDescriptor.

    Then there are further problems. When a getter or method is called via this kind of proxy, the this value passed to the getter or method will typically be the proxy itself. But as we saw earlier, many accessors and methods perform a type check that the proxy won’t pass. It would be better to substitute the target object for the proxy here. Can you figure out how to do it?

    The lesson to draw from this is that creating a proxy is easy, but creating a proxy with intuitive behavior is quite hard.

    Odds and ends

    • What are proxies really good for?

      They’re certainly useful whenever you want to observe or log accesses to an object. They’ll be handy for debugging. Testing frameworks could use them to create mock objects.

      Proxies are useful if you need behavior that’s just slightly past what an ordinary object can do: lazily populating properties, for example.

      I almost hate to bring this up, but one of the best ways to see what’s going on in code that uses proxies… is to wrap a proxy’s handler object in another proxy that logs to the console every time a handler method is accessed.

      Proxies can be used to restrict access to an object, as we did with readOnlyView. That sort of use case is rare in application code, but Firefox uses proxies internally to implement security boundaries between different domains. They’re a key part of our security model.

    • Proxies ♥ WeakMaps. In our readOnlyView example, we create a new proxy every time an object is accessed. It could save a lot of memory to cache every proxy we create in a WeakMap, so that however many times an object is passed to readOnlyView, only a single proxy is created for it.

      This is one of the motivating use cases for WeakMap.

    • Revocable proxies. ES6 also defines another function, Proxy.revocable(target, handler), that creates a proxy, just like new Proxy(target, handler), except this proxy can be revoked later. (Proxy.revocable returns an object with a .proxy property and a .revoke method.) Once a proxy is revoked, it simply doesn’t work anymore; all its internal methods throw.

    • Object invariants. In certain situations, ES6 requires proxy handler methods to report results that are consistent with the target object’s state. It does this in order to enforce rules about immutability across all objects, even proxies. For example, a proxy can’t claim to be inextensible unless its target really is inextensible.

      The exact rules are too complex to go into here, but if you ever see an error message like "proxy can't report a non-existent property as non-configurable", this is the cause. The most likely remedy is to change what the proxy is reporting about itself. Another possibility is to mutate the target on the fly to reflect whatever the proxy is reporting.

    What is an object now?

    I think where we left it was: “An Object is a collection of properties.”

    I’m not totally happy with this definition, even taking for granted that we throw in prototypes and callability as well. I think the word “collection” is too generous, given how poorly defined a proxy can be. Its handler methods could do anything. They could return random results.

    By figuring out what an object can do, standardizing those methods, and adding virtualization as a first-class feature that everyone can use, the ECMAScript standard committee has expanded the realm of possibilities.

    Objects can be almost anything now.

    Maybe the most honest answer to the question “What is an object?” now is to take the 12 required internal methods as a definition. An object is something in a JS program that has a [[Get]] operation, a [[Set]] operation, and so on.


    Do we understand objects better after all that? I’m not sure! Did we do amazing things? Yeah. We did things that were never possible in JS before.

    Can I use Proxies today?

    Nope! Not on the Web, anyway. Only Firefox and Microsoft Edge support proxies, and there is no polyfill.

    Using proxies in Node.js or io.js requires both an off-by-default option (--harmony_proxies) and the harmony-reflect polyfill, since V8 implements an older version of the Proxy specification. (A previous version of this article had incorrect information about this. Thanks to Mörre and Aaron Powell for correcting my mistakes in the comments.)

    So feel free to experiment with proxies! Create a hall of mirrors where there seem to be thousands of copies of every object, all alike, and it’s impossible to debug anything! Now is the time. There’s little danger of your ill-advised proxy code escaping into production… yet.

    Proxies were first implemented in 2010, by Andreas Gal, with code reviews by Blake Kaplan. The standard committee then completely redesigned the feature. Eddy Bruel implemented the new spec in 2012.

    I implemented Reflect, with code reviews by Jeff Walden. It’ll be in Firefox Nightly starting this weekend—all except Reflect.enumerate(), which is not implemented yet.

    Next up, we’ll be talking about the most controversial feature in ES6, and who better to present it than the person who’s implementing it in Firefox? So please join us next week as Mozilla engineer Eric Faust presents ES6 classes in depth.

  4. ES6 In Depth: Generators, continued

    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.

    Welcome back to ES6 In Depth! I hope you had as much fun as I did during our summer break. But the life of a programmer cannot be all fireworks and lemonade. It’s time to pick up where we left off—and I’ve got the perfect topic to resume with.

    Back in May, I wrote about generators, a new kind of function introduced in ES6. I called them the most magical feature in ES6. I talked about how they might be the future of asynchronous programming. And then I wrote this:

    There is more to say about generators… 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.

    Now is the time.

    You can find part 1 of this article here. It’s probably best to read that before reading this. Go on, it’s fun. It’s… a little long and bewildering. But there’s a talking cat!

    A quick revue

    Last time, we focused on the basic behavior of generators. It’s a little strange, perhaps, but not hard to understand. A generator-function is a lot like a regular function. The main difference is that the body of a generator-function doesn’t run all at once. It runs a little bit at a time, pausing each time execution reaches a yield expression.

    There’s a detailed explanation in part 1, but we never did a thorough worked example of how all the parts come together. Let’s do that now.

    function* someWords() {
      yield "hello";
      yield "world";
    }
    
    for (var word of someWords()) {
      alert(word);
    }
    

    This script is straightforward enough. But if you could observe everything that happens here, as though all the various bits of code were characters in a play, that would be a rather different script. It might go something like this:

    SCENE - INTERIOR COMPUTER, DAY
    
    FOR LOOP stands alone onstage, wearing a hard hat and
    carrying a clipboard, all business.
    
                              FOR LOOP
                             (calling)
                            someWords()!
                                  
    The GENERATOR appears: a tall, brass, clockwork gentleman.
    It looks friendly enough, but it's still as a statue.
    
                              FOR LOOP
                   (clapping her hands smartly)
               All right! Let's get some stuff done.
                         (to the generator)
                              .next()!
    
    The GENERATOR springs to life.
    
                             GENERATOR
                   {value: "hello", done: false}
    
    It freezes in a goofy pose.
    
                              FOR LOOP
                               alert!
    
    Enter ALERT at a sprint, wide-eyed and breathless. We sense
    he's always like that.
    
                              FOR LOOP
                       Tell the user "hello".
    
    ALERT turns around and sprints offstage.
    
                               ALERT
                       (offstage, screaming)
                          Stop everything!
              The web page at hacks.mozilla.org says,
                              "hello"!
    
    A few seconds' pause, then ALERT races back on, crossing all
    the way over to FOR LOOP and skidding to a halt.
    
                               ALERT
                         The user says OK.
    
                              FOR LOOP
                   (clapping her hands smartly)
               All right! Let's get some stuff done.
                  (turning back to the GENERATOR)
                              .next()!
    
    The GENERATOR again springs to life.
    
                             GENERATOR
                   {value: "world", done: false}
    
    It freezes in a different goofy pose.
    
                              FOR LOOP
                               alert!
    
                               ALERT
                         (already running)
                               On it!
                       (offstage, screaming)
                          Stop everything!
              The web page at hacks.mozilla.org says,
                              "world"!
    
    Again, a pause, then ALERT trudges back onstage, suddenly
    crestfallen.
    
                               ALERT
                   The user says OK again, but...
                 but please prevent this page from
                   creating additional dialogues.
    
    He exits, pouting.
    
                              FOR LOOP
                   (clapping her hands smartly)
               All right! Let's get some stuff done.
                  (turning back to the GENERATOR)
                              .next()!
    
    The GENERATOR springs to life a third time.
    
                             GENERATOR
                           (with dignity)
                   {value: undefined, done: true}
    
    Its head comes to rest on its chest and the lights go out of
    its eyes. It will never move again.
    
                              FOR LOOP
                      Time for my lunch break.
    
    She exits.
    
    After a while, the GARBAGE COLLECTOR enters, picks up the
    lifeless GENERATOR, and carries it offstage.
    

    All right—it’s not exactly Hamlet. But you get the picture.

    As you can see in the play, when a generator object first appears, it is paused. It wakes up and runs for a bit each time its .next() method is called.

    The action is synchronous and single-threaded. Note that only one of these characters is actually doing anything at any given time. The characters never interrupt each other or talk over one another. They take turns speaking, and whoever’s talking can go on as long as they want. (Just like Shakespeare!)

    And some version of this drama unfolds each time a generator is fed to a forof loop. There is always this sequence of .next() method calls that do not appear anywhere in your code. Here I’ve put it all onstage, but for you and your programs, all this will happen behind the scenes, because generators and the forof loop were designed to work together, via the iterator interface.

    So to summarize everything up to this point:

    • Generator objects are polite brass robots that yield values.
    • Each robot’s programming consists of a single chunk of code: the body of the generator function that created it.

    How to shut down a generator

    Generators have several fiddly extra features that I didn’t cover in part 1:

    • generator.return()
    • the optional argument to generator.next()
    • generator.throw(error)
    • yield*

    I skipped them mainly because without understanding why those features exist, it’s hard to care about them, much less keep them all straight in your head. But as we think more about how our programs will use generators, we’ll see the reasons.

    Here’s a pattern you’ve probably used at some point:

    function doThings() {
      setup();
      try {
        // ... do some things ...
      } finally {
        cleanup();
      }
    }
    
    doThings();
    

    The cleanup might involve closing connections or files, freeing system resources, or just updating the DOM to turn off an “in progress” spinner. We want this to happen whether our work finishes successfully or not, so it goes in a finally block.

    How would this look in a generator?

    function* produceValues() {
      setup();
      try {
        // ... yield some values ...
      } finally {
        cleanup();
      }
    }
    
    for (var value of produceValues()) {
      work(value);
    }
    

    This looks all right. But there is a subtle issue here: the call work(value) isn’t inside the try block. If it throws an exception, what happens to our cleanup step?

    Or suppose the forof loop contains a break or return statement. What happens to the cleanup step then?

    It executes anyway. ES6 has your back.

    When we first discussed iterators and the forof loop, we said the iterator interface contains an optional .return() method which the language automatically calls whenever iteration exits before the iterator says it’s done. Generators support this method. Calling myGenerator.return() causes the generator to run any finally blocks and then exit, just as if the current yield point had been mysteriously transformed into a return statement.

    Note that the .return() is not called automatically by the language in all contexts, only in cases where the language uses the iteration protocol. So it is possible for a generator to be garbage collected without ever running its finally block.

    How would this feature play out on stage? The generator is frozen in the middle of a task that requires some setup, like building a skyscraper. Suddenly someone throws an error! The for loop catches it and sets it aside. She tells the generator to .return(). The generator calmly dismantles all its scaffolding and shuts down. Then the for loop picks the error back up, and normal exception handling continues.

    Generators in charge

    So far, the conversations we’ve seen between a generator and its user have been pretty one-sided. To break with the theater analogy for a second:

    (A fake screenshot of iPhone text messages between a generator and its user, with the user just saying 'next' repeatedly and the generator replying with values.)

    The user is in charge. The generator does its work on demand. But this isn’t the only way to program with generators.

    In part 1, I said that generators could be used for asynchronous programming. Things you currently do with asynchronous callbacks or promise chaining could be done with generators instead. You may have wondered how exactly that is supposed to work. Why is the ability to yield (which after all is a generator’s only special power) sufficient? After all, asynchronous code doesn’t just yield. It makes stuff happen. It calls for data from files and databases. It fires off requests to servers. And then it returns to the event loop to wait for those asynchronous processes to finish. How exactly will generators do this? And without callbacks, how does the generator receive data from those files and databases and servers when it comes in?

    To start working toward the answer, consider what would happen if we just had a way for the .next() caller to pass a value back into the generator. With just this one change, we could have a whole new kind of conversation:

    (A fake screenshot of iPhone text messages between a generator and its caller; each value the generator yields is an imperious demand, and the caller passes whatever the generator wants as an argument the next time it calls .next().)

    And a generator’s .next() method does in fact take an optional argument, and the clever bit is that the argument then appears to the generator as the value returned by the yield expression. That is, yield isn’t a statement like return; it’s an expression that has a value, once the generator resumes.

      var results = yield getDataAndLatte(request.areaCode);
    

    This does a lot of things for a single line of code:

    • It calls getDataAndLatte(). Let’s say that function returns the string "get me the database records for area code..." that we saw in the screenshot.
    • It pauses the generator, yielding the string value.
    • At this point, any amount of time could pass.
    • Eventually, someone calls .next({data: ..., coffee: ...}). We store that object in the local variable results and continue on the next line of code.

    To show that in context, here’s code for the entire conversation shown above:

    function* handle(request) {
      var results = yield getDataAndLatte(request.areaCode);
      results.coffee.drink();
      var target = mostUrgentRecord(results.data);
      yield updateStatus(target.id, "ready");
    }
    

    Note how yield still just means exactly what it meant before: pause the generator and pass a value back to the caller. But how things have changed! This generator expects very specific supportive behavior from its caller. It seems to expect the caller to act like an administrative assistant.

    Ordinary functions are not usually like that. They tend to exist to serve their caller’s needs. But generators are code you can have a conversation with, and that makes for a wider range of possible relationships between generators and their callers.

    What might this administrative assistant generator-runner look like? It doesn’t have to be all that complicated. It might look like this.

    function runGeneratorOnce(g, result) {
      var status = g.next(result);
      if (status.done) {
        return;  // phew!
      }
    
      // The generator has asked us to fetch something and
      // call it back when we're done.
      doAsynchronousWorkIncludingEspressoMachineOperations(
        status.value,
        (error, nextResult) => runGeneratorOnce(g, nextResult));
    }
    

    To get the ball rolling, we would have to create a generator and run it once, like this:

      runGeneratorOnce(handle(request), undefined);
    

    In May, I mentioned Q.async() as an example of a library that treats generators as asynchronous processes and automatically runs them as needed. runGeneratorOnce is that sort of thing. In practice, generator will not yield strings spelling out what they need the caller to do. They will probably yield Promise objects.

    If you already understand promises, and now you understand generators, you might want to try modifying runGeneratorOnce to support promises. It’s a difficult exercise, but once you’re done, you’ll be able to write complex asynchronous algorithms using promises as straight-line code, not a .then() or a callback in sight.

    How to blow up a generator

    Did you notice how runGeneratorOnce handles errors? It ignores them!

    Well, that’s not good. We would really like to report the error to the generator somehow. And generators support this too: you can call generator.throw(error) rather than generator.next(result). This causes the yield expression to throw. Like .return(), the generator will typically be killed, but if the current yield point is in a try block, then catch and finally blocks are honored, so the generator may recover.

    Modifying runGeneratorOnce to make sure .throw() gets called appropriately is another great exercise. Keep in mind that exceptions thrown inside generators are always propagated to the caller. So generator.throw(error) will throw error right back at you unless the generator catches it!

    This completes the set of possibilities when a generator reaches a yield expression and pauses:

    • Someone may call generator.next(value). In this case, the generator resumes execution right where it left off.
    • Someone may call generator.return(), optionally passing a value. In this case, the generator does not resume whatever it was doing. It executes finally blocks only.
    • Someone may call generator.throw(error). The generator behaves as if the yield expression were a call to a function that threw error.
    • Or, maybe nobody will do any of those things. The generator might stay frozen forever. (Yes, it is possible for a generator to enter a try block and simply never execute the finally block. A generator can even be reclaimed by the garbage collector while it’s in this state.)

    This is not much more complicated than a plain old function call. Only .return() is really a new possibility.

    In fact, yield has a lot in common with function calls. When you call a function, you’re temporarily paused, right? The function you called is in control. It might return. It might throw. Or it might just loop forever.

    Generators working together

    Let me show off one more feature. Suppose we write a simple generator-function to concatenate two iterable objects:

    function* concat(iter1, iter2) {
      for (var value of iter1) {
        yield value;
      }
      for (var value of iter2) {
        yield value;
      }
    }
    

    ES6 provides a shorthand for this:

    function* concat(iter1, iter2) {
      yield* iter1;
      yield* iter2;
    }
    

    A plain yield expression yields a single value; a yield* expression consumes an entire iterator and yields all values.

    The same syntax also solves another funny problem: the problem of how to call a generator from within a generator. In ordinary functions, we can scoop up a bunch of code from one function and refactor it into a separate function, without changing behavior. Obviously we’ll want to refactor generators too. But we’ll need a way to call the factored-out subroutine and make sure that every value we were yielding before is still yielded, even though it’s a subroutine that’s producing those values now. yield* is the way to do that.

    function* factoredOutChunkOfCode() { ... }
    
    function* refactoredFunction() {
      ...
      yield* factoredOutChunkOfCode();
      ...
    }
    

    Think of one brass robot delegating subtasks to another. You can see how important this idea is for writing large generator-based projects and keeping the code clean and organized, just as functions are crucial for organizing synchronous code.

    Exeunt

    Well, that’s it for generators! I hope you enjoyed that as much as I did, too. It’s good to be back.

    Next week, we’ll talk about yet another mind-blowing feature that’s totally new in ES6, a new kind of object so subtle, so tricky, that you may end up using one without even knowing it’s there. Please join us next week for a look at ES6 proxies in depth.

  5. Developer Edition 41: View source in a tab, screenshot elements, HAR files, and more

    When we introduced the new Performance tools a few weeks ago, we also talked about how the Firefox Dev Tools team had spent a lot of time focusing on user feedback and what we call ‘polish’ bugs – things reported via our UserVoice feedback channel and Bugzilla. Even though the Firefox 41 was a short release cycle for us, this focus on user feedback continues to pay off — several new features that our community had been asking for landed in time for the release. Here’s a closer look:

    Screenshot the selected node in the Inspector

    New contributor Léon McGregor implemented an interesting suggestion that was posted in UserVoice. This functionality has been available via the gcli ‘screenshot’ command for quite some time, but is much more discoverable and useful as a context menu item. When the screenshot is created, Firefox copies it to your configured downloads directory.

    Create a screenshot of the currently selected element.

    Create a screenshot of the currently selected element.

    View source in tab

    Starting with Firefox 41, when you right-click and select View Page Source, the html source view will open in a tab instead of a new window. This was a hugely popular request and we would have shipped it earlier but what started out as a seemingly simple change was actually quite involved: See the bug linked below for all the gory details. Importantly, we have also ensured that View Page Source provides you with the source of the page as-is from Firefox’s cache – we do not fetch a new version.

    'View source' always opens in a tab now.

    View Page Source always opens in a tab now.

    Add Rules button

    It’s very convenient to be able to add a new rule to the Inspector as you work, and this is a feature from Firebug that users have requested for some time. During this last cycle, we spent some time polishing our implementation, and provided the convenience of a UI button in addition to the context menu command.

    We've added a button to the inspector so you can quickly add a new css rule.

    We’ve added a button to the inspector so you can quickly add a new css rule.

    “Copy as HAR” and “Save all as HAR”

    Another feature from Firebug that is particularly popular with Selenium users is the ability to export HAR archives for the current page.

    You can now export HAR archives directly from the network monitor.

    You can now export HAR archives directly from the network monitor.

    Other notable changes

    In total, 140 Developer Tools bugs have been fixed in Firefox since June 1st. On behalf of the team, I’d like to thank all of the people who reported bugs, tested patches, and spent many hours working to improve this version of Firefox Developer Edition, and especially these contributors that fixed bugs: edoardo.putti, fayolle-florent, 15electronicmotor, veeti.paananen, sr71pav, sjakthol, ntim, MattN, lemcgregor3, and indiasuny000. Thanks!.

    • Bug 1164210 – $$() should return a true Array
    • Bug 1077339 – Display keyboard shortcuts when hovering panel tabs
    • Bug 1163183 – Show HTML5 Forms pseudo elements in the rule view
    • Bug 1165576 – Netmonitor theme refresh
    • Bug 1049888 – Make the storage actor work in e10s and Firefox OS
    • Bug 987365 – Add pseudo-class lock options to rule view
    • Bug 1059882 – Frame selection command button should be visible by default
    • Bug 1143224 – Opening the netmonitor slows down requests on the page
    • Bug 1119133 – Keyboard shortcut to toggle devtools docking mode between last two positions
    • Bug 1024693 – Copy CSS declarations
    • Bug 1050691 – Click on a function on the console should go to the debugger

    Download Firefox Developer Edition 41 now. Let us know what you think and what you’d like to see in future releases. We’re paying attention.

  6. Compacting Garbage Collection in SpiderMonkey

    Overview

    Compacting is a new feature of our garbage collector, released in Firefox 38, that allows us to reduce external fragmentation in the JavaScript heap. The aim is to use less memory in general and to be able to recover from more out-of-memory situations. So far, we have only implemented compacting for JavaScript objects, which are one of several kinds of garbage-collected cells in the heap.

    The problem

    The JavaScript heap is made up of 4K blocks of memory called arenas, each of which is divided into fixed-size cells. Different arenas are used to allocate different kinds of cells; each arena only contains cells of the same size and kind.

    The heap contains various kinds of cell, including those for JavaScript objects, strings, and symbols, as well as several internal kinds such as scripts (used to represent units of JS code), shapes (used to determine the layout of object properties in memory), and jitcode (compiled JIT code). Of these, object cells usually take up the most memory.

    An arena cannot be freed while it contains any live cells. Cells allocated at the same time may have different lifetimes and so a heap may end up in a state where there are many arenas that contain only a few cells. New cells of the same kind can be allocated into this space, but the space cannot be used for cells of a different kind or returned to the operating system if memory is low.

    Here is a simplified diagram of some data on the heap showing arenas containing two different kinds of cell:

    heap layout smallest

    Note that if the free space in arena 3 were used to hold the cells in arena 5, we could free up a whole arena.

    Measuring wasted heap space

    You can see how much memory these free cells are taking up by navigating to about:memory and hitting the ‘Measure’ button. The totals for the different kinds of cell are shown under the section js-main-runtime-gc-heap-committed/unused/gc-things. (If you’re not used to interpreting the about:memory reports, there is some documentation here).

    Here’s a screenshot of the whole js-main-runtime-gc-heap-committed section with compacting GC disabled, showing the difference between ‘used’ and ‘unused’ sizes:

    unused heap screenshot

    I made some rough measurements of my normal browsing profile with and without compacting GC (details of how to do this are below at the end of the post). The profile consisted of Google Mail, Calendar, many bugzilla tabs and various others (~50 tabs total), and I obtained the following readings:

    Total explicit allocations Unused cells
    Before compacting 1,324.46 MiB 69.58 MiB
    After compacting 1,296.28 MiB 40.18 MiB

    This shows a reduction of 29.4MiB (mebibytes) worth of explicit allocations. That’s only about 2% of total allocations, but accounts for over 8% of the space taken up by the JS heap.

    How does compacting work?

    To free up this space we have to allow the GC to move cells between arenas. That way it can consolidate the live cells in fewer arenas and reuse the unused space. Of course, this is easier said than done, as every pointer to a moved cell must be updated. Missing a single one is a sure-fire way to make the browser crash!

    Also, this is a potentially expensive operation as we have to scan many cells to find the pointers we need to update. Therefore the idea is to compact the heap only when memory is low or the user is inactive.

    The algorithm works in three phases:

    1. Select the cells to move.
    2. Move the cells.
    3. Update the pointers to those cells.

    Selecting the cells to move

    We want to move the minimum amount of data and we want to do it without allocating any more memory, as we may be doing this when we don’t have any free memory. To do this, we take all the arenas with free space in them and put them in a list arranged in decreasing order of the number of free cells they contain. We split this list into two parts at the first point at which the preceding arenas have enough free cells to contain the used cells in the subsequent arenas. We will move all the cells out of the subsequent arenas.

    Moving the cells

    We allocate a new cell from one of the arenas we are not moving. The previous step ensures there is always enough space for this. Then we copy the data over from the original location.

    In some cases, we know the cell contains pointers to itself and these are updated at this point. The browser may have external references to some kinds of object and so we also call an optional hook here to allow these to be updated.

    When we have moved a cell, we update the original location with a forwarding pointer to the new location, so we can find it later. This also marks the cell, indicating to the GC that the cell has been moved, when updating pointers in the next phase.

    Updating pointers to moved cells

    This is the most demanding part of the compacting process. In general, we don’t know which cells may contain pointers to cells we have moved, so it seems we have to iterate through all cells in the heap. This would be very expensive.

    We cut down this cost in a number of ways. Firstly, note that the heap is split into several zones (there is a zone per browser tab, and others for system use). Compacting is performed per-zone, since in general cells do not have cross-zone pointers (these are handled separately). Compacting per zone allows us to spread the total cost over many incremental slices.

    Secondly, not every kind of cell can contain pointers to every other kind of cell (indeed not all kinds of cells can contain pointers) so some kinds of cell can be excluded from the search.

    Finally, we can parallelise this work and make use of all CPU resources available.

    It’s important to note that this work was enabled by our shift to exact stack rooting, described in this blog post. It is only possible to move objects if we know which stack locations are roots, otherwise we could overwrite unrelated data on the stack if it happened to look like a moved cell pointer.

    Scheduling heap compaction

    As mentioned earlier, compacting GC doesn’t run every time we collect. Currently it is triggered on three events:

    • We ran out of memory and we’re performing a last-ditch attempt to free up some space
    • The OS has sent us a memory pressure event
    • The user has been inactive for some length of time (currently 20 seconds)

    The first two should allow us to avoid some out-of-memory situations, while the last aims to free up memory without affecting the user’s browsing experience.

    Conclusion

    Hopefully this has explained the problem compacting GC is trying to solve, and how it’s done.

    One unexpected benefit of implementing compacting GC is that it showed us a couple of places where we weren’t correctly tracing cell pointers. Errors like this can cause hard-to-reproduce crashes or potential security vulnerabilities, so this was an additional win.

    Ideas for future work

    The addition of compacting is an important step in improving our GC, but it’s not the end by any means. There are several ways in which we can continue to develop this:

    Currently we only compact cells corresponding to JavaScript objects, but there are several other kinds of cells in the heap. Moving these would bring greater memory savings.

    Is it possible to determine in advance which cells contain pointers to cells we want to move? If we had this information we could cut the cost of compacting. One possibility is to scan the heap in the background to determine this information, but we would need to be able to detect changes made by the mutator.

    The current algorithm mixes together cells allocated at different times. Cells with similar lifetimes are often allocated at the same time, so this may not be the best strategy.

    If compacting can be made fast enough, we might be able to do it whenever the collector sees a certain level of fragmentation in the heap.

    How to measure heap space freed up by compacting

    To measure roughly how much space is freed by compacting, you can perform the following steps:

    1. Disable compacting by navigating to about:config and setting javascript.options.mem.gc_compacting to false.
    2. It makes it easier to disable multiprocess Firefox as well at this point. This can be done from the main Preferences page.
    3. Restart the browser and open some tabs. I used ‘Reload all tabs’ to open all my pages from last time. Wait for everything to load.
    4. Open about:memory and force a full GC by clicking ‘Minimize memory usage’ and then click ‘Measure.’ Since memory usage can take a while to settle down, I repeated this a few times until I got a consistent number.
    5. Note the total ‘explicit’ size and that of js-main-runtime-gc-heap-committed/unused/gc-things.
    6. Enable compacting again by setting javascript.options.mem.gc_compacting to true. There is no need to restart for this to take effect.
    7. Click ‘Minimize memory usage’ again and then ‘Measure.’
    8. Compare the new readings to the previous.

    This does not give precise readings as all kinds of things might be happening in the background, but it can provide a good ballpark figure.

  7. 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.

  8. 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

  9. 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.

    Note: There is now a Vietnamese translation of this post, created by Julia Duong of the Coupofy team.

    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!

  10. 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.