GitHub - KoryNunn/es-twentysixnext: contains both facts and opinions about es-whateverthefuck

9 min read Original article ↗

es-twentynextsixbabel

Warning: contains both facts and opinions about es-whateverthefuck.

Many things taken from here: https://github.com/lukehoban/es6features

My opinions are subject to pull requests.

arrows

What

Shorthand functions, implicit returns^

[1, 2, 3].map(x => x * 2) // -> [2, 4, 6]

Also doesn't bind scope...

Why

People don't like hitting lots of keys. People don't like thinking about this

The good

Great for little throw-away-style expressions. Great in functional style code eg:

var names = arrayOfPeople.map(person => person.name);

The bad.

There are many forms:

No braces:

some braces:

some other braces:

x => { x+= 20; return x.toString(); }

tuns-o-braces:

(x, y) => { x += y; return x.toString(); }

The Ugly

So many versions

^: Implicit returns, unless you use curly braces, obviously.

var doThing1 = x => x;

doThing1(10); // -> 10

var doThing2 = x => {x};

doThing2(10); // -> undefined

var doThing3 = (x) => {x};

doThing3(10); // -> undefined

var doThing4 = (x) => x;

doThing4(10); // -> 10

var doThing5 = (x) => {return x};

doThing5(10); // -> 10

var doThing5 = x => return x; // -> Uncaught SyntaxError: Unexpected token return

Plays well with other es-sinex15 features

Say I have a value, and I want to turn that into an object like so:

You can do this in es-sinex15 like so:

Cool! let's throw in some arrow functions:

[1, 2, 3].map(x => {x}) // -> [undefined, undefined, undefined]

Awesome. Wrap it in another layer of braces then..

[1, 2, 3].map(x => {{x}}) // -> [undefined, undefined, undefined]

Oh right, no implicit returns anymore..

[1, 2, 3].map(x => {return {x}}) // -> [{x: 1}, {x: 2}, {x: 3}]

Nice..

Of course you can use parentheses to get the result we want:

[1, 2, 3].map(x => ({x})) // -> [{x: 1}, {x: 2}, {x: 3}]

classes

I can't. No. Just don't.

enhanced object literals

What

Allows you to construct objects a bit nicer:

var x = 10;

var obj = {x};

obj // -> {x: 10};

Also now supports computed properties:

var value = 'World',
    obj = {
        ['hello' + value]: value
    };

obj // -> {helloWorld: 'World'}

The good

Being able to make objects without repeating yourself is quite handy, and being able to create computed properties without using [someKey] is pretty good too.

function createPerson(firstName, surname, age){
    return {firstName, surname, age};
}

The Bad

Functionally, there is nothing bad about these features

Nevermind, of cource there are problems.

var x = {y} //legit
var x = {get} // fucked

Because get is a magic property used for getter/setters..

NEVERMIND AGAIN! That was just a v8 bug which is now fixed.

The ugly

WHY DID THEY USE SQUARE BRACES FOR COMPUTED PROPERTIES!?

If only there was an existing way to say 'Do this first', OH WAIT!

// Calculate 5 + 6 first.
var x = (5 + 6) * 10;

Wouldn't that have been nicer?

{
    // CALCULATE THIS: THEN ASSIGN THIS!
    ('hello' + value): value
}

Also literals get a little confusing when you mix'n'match:

template strings

What

Exactly what you'd expect. Template values into a string.

Oh but also just jam multiline support together with it because.

var myString = `Hello world,
Hey look multiline! Also, lets pull ${anything} from scope`;

The good

Umm.. I guess multiline is cool? oh but wait..

The bad

Why do template strings even exist? Let's write a function that implements template strings, with the added bonus of the string not pulling random crap from scope:

var template = (string, scope) => string.replace(/\$\{(.+?)\}/g, (match, key) => scope[key]);

var world = 'planet';

template('Hello ${world}', {world}) // -> 'Hello planet'

Wow I can see why that's a language feature..

Also, you can't put the template in a variable and use it later, since it immediately evaluates.

Also, using your own function means that you can decide what your token syntax is.

The ugly

How do you do multiline when you're in a non-whitespace-sensitive language? Badly! :D

var greeting = `Hello!
    How are you today?`

greeting // -> "Hello!\n    How are you today?"

Yeah so if you're in a block, just mess everything up:

function foo(){

    function bar(){
        return `my
cool
multi
line
string`;
    }

}

Nice...........

destructuring

Assign values to variables out of objects using pattern matching.

function distance(point1, point2){
    var [x1, y1] = point1,
        [x2, y2] = point2;

    return Math.sqrt(
        Math.pow(x1 - x2, 2) +
        Math.pow(y1 - y2, 2)
    );
}

distance([10, 10], [20, 20]);
// -> 14.142135623730951

The good

Everything. This is a good feature.

The Bad

Can't see any issues

The ugly

Its power may lead to mess, since you can do deep matching (which is also cool)

var {foo: {bar: {baz: {x: x}}}} = obj;

default + rest + spread

What

Defaults:

function foo(x=10){
    return x;
}

foo(5) // -> 5
foo() // -> 10

Rest:

function foo(a, b, c...){
    return a + b + c.join(' ');
}

foo('a', 'b', 'c', 'd', 'e', 'f') // -> 'abcdef'

Spread:

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

add(1, 2) // -> 3

var values = [3, 4];
add(...values) // -> 7

The good

Again, this stuff is excelent. These are features that you can't trivially implement with plain javascript.

The ugly

Defaults accept destructuring assignment. This is a HORRIBLE HORRIBLE feature!

Via @yoshuawuyts

var fn = ({foo = 3, bar = 4} = {}) => {};

READABILITY--!

let + const

UUuuuuguhhh.

let: block scoped var

const let but you can't assing to it twice.

The good

Um.. I guess if you aren't used to lexical scoping..?

The bad

let is just var but block-scoped. Rather than spending 20s to learn how JS works, let's add syntax.

The ugly

Attempting to assign a value to a const after declaration silently fails, but returns the value you attempted to assign.

const x = 10; // -> 10

x = 20; // -> 20

x; // -> 10

UPDATE: FIXED! latest browsers and node now throw.

Declairing a const without immediately assigning a value results in undefined as expected, which is effectivly totally pointless.

const x; -> undefined, forever. Pointless.

UPDATE: FIXED! latest browsers and node now throw.

iterators + for..of

What

Allows for custom implementation of iterators.

I haven't looked too far into these, but they look ok so far.

The good, bad, ugly

Sorry, I'm lazy, you'll have to find out for yourself :)

generators

What

Used in languages that don't have first-class functions to return a different value each time the function is called.

The good

???

The bad

This is just pointless sugar. You can implement the functionality of generators trivially in ES3.

Stolen directly from https://github.com/lukehoban/es6features

Fibonacci with generators:

var fibonacci = {
  [Symbol.iterator]: function*() {
    var pre = 0, cur = 1;
    for (;;) {
      var temp = pre;
      pre = cur;
      cur += temp;
      yield cur;
    }
  }
}

The same shit without generators:

var fibonacci = function(){
  [Symbol.iterator]() {
    let pre = 0, cur = 1;
    return {
      next() {
        [pre, cur] = [cur, pre + cur];
        return { done: false, value: cur }
      }
    }
  }
}

Same length, same functionality, why bother.

The ugly

They exist.

unicode

There is new unicode support. Seems fine, I'm lazy, ¯\(ツ)

modules

What

Like require() but hard-baked into the language, and using import and export instead.

someModule.js

export function foo(){
    return 'bar';
}

anotherModule.js

import foo from 'someModule.js';

foo() // -> 'bar';

The good

???

The bad

It's the same as require but with quirks. You can do all the destructiong with, supprise, destructuring.

The ugly

Nothing super bad that I know of.

module loaders

Kinda ties in with the above stuff, allows you to screw with the module cache. I'm going to ¯\(ツ)/¯ this one too.

map + set + weakmap + weakset

What

Map: key: value where key can be any value at all, including objects/functions. Set: Distinct list of any value. Can be itterated over. WeakMap: key: value where key must be an instance of an object (or function). References are weakly held. WeakSet: Distinct list of references. Cannot be itterated over, only checked if it contains a value.

Too much to go into in this talk.

The good

These are great additions to JS, they cannot be implemented in ES3, and are non-trivial to implement in ES5, and polyfills are slow.

Weak(map/set) are especially excelent, and open up a whole range of options that were previously impossible/impractical.

The bad

Nothing really, safari doesn't implement iterators correctly? Not really a fault of the spec.

The ugly

Nothing.

proxies

What

Literally proxy an object, and have control over what gets done to it:

var obj = {};

var proxy = new Proxy(obj, {
        get: function(target, propertyName){
            return propertyName in obj ? obj[propertyName] : 'Never set!';
        },
        set: function(target, propertyName, value){
            obj[propertyName] = value;
        }
    });

Opens up the ability to create some nice apis:

var crel = new Proxy(actualCrel, {
    get: function(target, propertyName){
        return target.bind(target, propertyName);
    }
})

crel('div', {class: 'foo'}); // -> <div class="foo"></div>
crel.div({class: 'foo'}); // -> <div class="foo"></div>

symbols

What

like magical private strings that allow access to a property if you have the symbol

var mySymbol = Symbol('arbitraryString');

var obj = {};

obj[mySymbol] = 'foo';

// Can only be accessed if you have the instance of the symbol
obj[mySymbol]; // -> 'foo'


// Creating a new symbol with the same string will not work
obj[Symbol('arbitraryString')]; // -> undefined

The good

I'm not sure if these are really that useful. Maybe? You can do pretty much the same thing with WeakMap's and objects.

Symbols are a little neater I guess

The bad

They are mostly sugar, but do add some legitimacy around privitized properties.

The ugly

Nothing really.

subclassable built-ins

What

You can now create constructors with Array/Date/Element prototypes

The good

This is an actual feature. This was previosuly hard/impossible to do properly.

The bad

Seems mostly good.

The ugly

There is a @@create property. It exists for a reason, but it's just ugly.

promises

What

Just callbacks but with crap around them to make sure you have no idea where an error came from.

The good

I honestly have never come across any situation where promises have looked like a good solution.

The bad.

** BEGIN RANT **

The ugly

** CONTINUE RANT **

SHAMELESS PLUG: I made a thing that is what I'd have like promises to be: https://github.com/KoryNunn/righto

math + number + string + array + object APIs

What

There are new Math.x functions, like EPSILON, acosh, imul, hypot, isInteger, etc..

The good

All looks good to me!

binary and octal literals

They exist now:

0b111110111 === 503 // true
0o767 === 503 // true

tail calls

What

They work in certian situations now without adding stack.

They seem fine.