Javascript, ES6/ES2015 Discussion Thread


  • Tiger Hat

    It was mentioned in Lostcast 150 that the LDG crew have “been hearing a lot about ES6 or ES2015”. The sentiment was generally that JavaScript can already do that, and so we don’t need it. Well it was finalized by the standards body in June of 2015, and they are already working on ES2016 features. Right now, it is true however that most browsers / engines (node.js) haven’t fully implemented all of the features yet, but they will. I wanted to start this thread to talk about what I personally think is actually very exciting and useful for JavaScript developers, and to discuss it outside of the Lostcast thread so that it doesn’t fade away after the next episode.

    First, a couple of resources to help. Exploring ES6 e-book by Dr. Axel Rauschmayer is freely readable online and probably the best resource that I’ve found documentation wise. Also Babel which is a “transpiler” that enables you to write code using features from future versions of ECMAScript (JavaScript) today and compile them down to supported versions.

    So yes, it is true that JavaScript can accomplish most of the new features already, this is what makes “transpiling” possible, however it can make code cleaner, development easier, and add standard ways of doing things. Take classes for example (again, not suggesting that a deep tree hierarchy is used, but a few classes are a good thing). Here is your ES5 way to accomplish it:

    function Animal(name) {
        this.name = name;
    }
    
    Animal.prototype.speak = function() {
        console.log('meow');
    }
    

    And here is the same class in ES2015:

    class Animal {
        constructor(name) {
            this.name = name;
        }
    
        speak() {
            console.log('meow');
        }
    }
    

    IMO using classes here makes it more obvious that it’s a class, more obvious that the initial function is a constructor, as well as cleaner to define the method without having to use Animal.prototype. It’s also easier to subclass:

    function Dog() {
        Animal.call(this, 'dog');
    }
    
    Dog.prototype = Object.create(Animal.prototype);
    Dog.prototype.constructor = Dog;
    
    Dog.prototype.speak = function() {
        console.log('woof');
    };
    

    vs

    class Dog extends Animal {
        constructor() {
            super('dog');
        }
    
        speak() {
            console.log('woof');
        }
    }
    

    Again IMO that is much more readable and easier to follow. There are fewer “tricks” to know.

    There are a LOT of new features, and I recommend just start using a couple of them here and there, slowly introducing more and more until they just become part of your everyday use. We can talk more about cool stuff like arrow functions and block scoping, iterators and generators and all that. But I’ll let classes stew for a bit first :)


  • LDG

    Good stuff. The class syntax is much better, I agree. Do you know if there’s any difference in the underlying implementation or is it sugar around setting the prototype?

    I’ve actually been using the fat arrow for some newer code since Chrome supports it. My general stance is to avoid transpilers, but I’ve been hearing about Babel quite a bit recently. Although, I’d much prefer to stick to features with are at least functional in Chrome with Vanilla JS.

    The biggest feature I’m interested in is module support. Ditching RequireJS/browserify/etc would be nice! As far as I can tell, module support in Babel just converts the ES6 style in CommonJS, AMD, etc, though. It appears that the module loading part of the spec isn’t even complete, yet.


  • Tiger Hat

    I believe that the underlying implementation is changed, in the book it is discussed a bit here but it has to do with how things are instantiated. For the “normal” class usage I don’t believe that it makes a difference (which is why it can be transpiled), however you need the engine changes to be able to subclass built in classes like Error and Array.

    Modules are one of my favorite things as well. It’s true that they get transpiled to CommonJS etc right now, but that doesn’t stop your source code from using it. Since you’re going to have a build system anyway, why not? :) I’ve had a lot of luck using jspm, it makes it easy to use ES6 modules as well as gives you the package mgmt of Bower and NPM combined.

    Starting out with what Chrome supports sounds like a great idea, certainly no matter how easy to use a transpiler or package manager is, just hacking away in the dev tools is easier :)


  • Patron

    Call me whatever you want, but this is what I like:

    function Animal(name)
    {
     return {name : name, speak : function() {console.log("meow")}};
    }
    
    

    Ok, maybe not exactly like this, but… you get the general idea: an object “factory”, or prefab system or whatever you call this.
    I know, I know, then you lose all the benefits of prototype inheritance and all, but… how often is that used in an entity component system, anyways?

    Yeah… I’m getting convinced that I’m just a C99 aficionado living in a Javascript programmer’s body.
    I WANT ALL MY DATA TO BE BINARY!

    P.S: I guess I should resume my long overdue read of Learning C The Hard Way.



  • @geoffb said:

    My general stance is to avoid transpilers, but I’ve been hearing about Babel quite a bit recently.

    I write all my new JavaScript in ES6 using Babel.
    But, having that extra compile step is definitely something I would prefer to avoid.
    Plus, having to deal with source maps (and hoping that Chrome loads them correctly) is another thing that will wear on your nerves after a while.
    All that said, the extra conveniences of ES6, even through a transpiler, have been worth it for me.

    But, I think that unless you’re starting a completely new project from scratch, I wouldn’t suddenly start updating all your old code to ES6.
    As others have mentioned, there’s nothing new you can do in ES6 that you couldn’t do in ES5/3 - just some things are more convenient and the syntax is cleaner.
    And a huge number of the new ES6 features are really for marginal use cases: to make JS a better compile-to target, and for code library designers.
    So, I think your conservative implementation of just the features the browsers support natively is a wise decision.

    The biggest feature I’m interested in is module support. Ditching RequireJS/browserify/etc would be nice! As far as I can tell, module support in Babel just converts the ES6 style in CommonJS, AMD, etc, though. It appears that the module loading part of the spec isn’t even complete, yet.

    Can anyone reading this point us to a pain-free (easy!) way to implement ES6 modules using Babel?
    (I believe Babel interprets the ES6 module code to RequireJS/browserify/etc under-the-hood, so you still that dependency… ?)

    Do you know if there’s any difference in the underlying implementation or is it sugar around setting the prototype?

    It’s just sugar syntax: a prettier way to create a function that returns an object.
    Like Josue, I prefer to create objects using functional factories and mixins.
    It’s just for aesthetic reasons really: it means I don’t have to look at this, prototype and new all over my code, and to my mind the object creation processes feel more concrete.


  • Tiger Hat

    @d13 said:

    Can anyone reading this point us to a pain-free (easy!) way to implement ES6 modules using Babel?
    (I believe Babel interprets the ES6 module code to RequireJS/browserify/etc under-the-hood, so you still that dependency… ?)

    You should check out jspm it uses system.js as the loader I believe, which is also what supports native modules. It really does make it “easy” IMO, and it will bundle up / browerify anything you need for you as well as generate source maps.

    Also, I think that you very much can and should start using ES6 features in your current projects. Yes, switching to modules is likely something to wait for a new project, but any time you add new code or touch a method you could refactor.

    Another awesome feature is Destructuring which enables (among other things) the rest operator and default parameters. Again, even though you can do all of this in ES5, it’s about code readability, which when you’re working on a team is very important.

    Rest Operator:

    function add(a, b, ...others) {
        if(others && others.length) {
            return a + b + others.reduce((i, j) => i + j);
        }
        return a + b;
    }
    

    vs ES5

    function add(a, b) {
        var others = Array.prototype.slice.call(arguments, 2);
        if (others && others.length) {
            return a + b + others.reduce(function(i, j) { return i + j; });
        }
        return a + b;
    }
    

    Default parameters:

    function add(a, b=1) {
        return a + b;
    }
    

    vs.

    function add(a, b) {
        b = isNaN(b) ? 1 : b;
        return a + b;
    }
    

    General Destructuring:

    function multiMath(a, b) {
        return {sum: a + b, difference: a - b, product: a * b, dividend: a / b};
    }
    
    let values = [2, 3];
    let {sum, product} = multiMath(...values);
    console.log(`sum is ${sum}, product is ${product}`);
    

    vs.

    function multiMath(a, b) {
        return {sum: a + b, difference: a - b, product: a * b, dividend: a / b};
    }
    
    var values = [2, 3];
    var result = multiMath(values[0], values[1]);
    var sum = result.sum;
    var product = result.product;
    console.log('sum is ' + sum + ', product is ' + product);
    

    These types of changes make your intentions clearer without having to really “read” the code to see what’s happening. It also really helps IDEs analyze your code to provide suggestions (intellisense). And of course, it’s also much cleaner and prettier (IMO).

    I used the spread operator and template strings in that last one.



  • @Warspawn said:

    You should check out jspm

    Thank you, that’s just what I was looking for!


  • Tiger Hat

    I made this tutorial just before the holidays, and it got published somewhere in between…
    https://html5hive.org/es6-and-babel-tutorial/