ECMAScript (in) 2015

The future is now!

Let's talk about...

ECMAScript 2015

was called ES6

was called ES.next

was refered as Harmony

is the spec for JavaScript's next version (btw)

The new name has a purpose

It shows that the spec will now be released on an annual cadence

The next version, previously ES7, will be called ES2016, etc

So the new name conveys better the intentions

Even if most people liked ES 6, and lots of resources call it that

And even if it feels like a Windows version name

It also feels like a signal:

It's time to upgrade

Or do you want to be writing "legacy code"?

The future is now!

Final release in June!

(And it is 99% done, feature frozen, in release candidate)

By the way, where are we on ES2015 support?

Estimate of % of features implemented:

Of course, the supported parts do not necessarily overlap

Feature Firefox Chrome
Destructuring
Object.observe (ES2016)

Introducing transpilers

Can compile ES2015 code to ES5

Don't support everything, but most features

"Just another build step"

Babel's website is awesome.

Use it and start working 30s later

(And yes, lots of companies use it in production)

Now to ES2015's content

I've been babbling for a while about the "how", not the "why"

  1. new Syntax
  2. new Functionalities

Block scoping: let

for (var i = 0; i < 5; i++) {
  var tmp = Math.pow(i, i);
}
console.log(i, tmp); // 5, 256

Block scoping: let

for (let i = 0; i < 5; i++) {
  let tmp = Math.pow(i, i);
}
console.log(i, tmp); // ReferenceError: i, tmp are not defined

Block scoping: const

const AWESOME_MEETUP = 'ParisJS';
AWESOME_MEETUP = 'Another place'; // TypeError
if (true) {
  const AWESOME_MEETUP = 'ParisJS';
}
console.log(AWESOME_MEETUP); // ReferenceError

Methods

var obj = {
  sayHello: function(name) {
    console.log(name);
  }
}
var obj = {
  sayHello(name) {
    console.log(name);
  }
}

Arrow functions

// ES5
['Vivement', 'Les', 'Pizzas'].map(function(s) {
  return s.toUpperCase();
});
// ES2015
['Vivement', 'Les', 'Pizzas'].map(s => s.toUpperCase());

Arrow functions

Look at this!

Suppose we're in an object with this.logger defined

var self = this; // ES3: Saving this
article.save(function(err) {
  if (err) this.logger.error(err);
}.bind(this)); // ES5: bind
// ES2015: Lexical this
article.save((err) => {
  if (err) this.logger.error(err);
});

Spread Operator

Math.max([1,2,3,4]); // NaN
Math.max(...[1,2,3,4]); // 4

Rest parameters

Get arguments, get rid of "arguments"

function randomCallback(err, ...params) {
  console.log(params); // [1, 2, 3, 4, 5]
}
randomCallback(null, 1, 2, 3, 4, 5)

Default parameters

function sayHello(name = 'ParisJS') {
  console.log('Hello ' + name);
}
sayHello(); // Hello ParisJS
sayHello('Pizzas'); // Hello Pizzas

Short-hands to build objects...

var text = 'Hello ParisJS';
var images = [];
var object = {};
// ES5
var resources = { text: text, images: images, object : object };
// ES6
let resources = { text, images, object };

and destructuring

let { max, min } = Math;
max(1,2,3,4);
min(1,2,3,4);

Template strings

var name = 'ParisJS';
var text = `I'm speaking at ${name}
Oh god the text
is going on multiple lines
It's incredible!`

Modules - named exports & imports

// meetup.js
export const BEST_MEETUP = 'ParisJS';
export function speak(s) { console.log(s)};
// main.js
import { BEST_MEETUP, speak } from './meetup.js';
speak(BEST_MEETUP); // 'ParisJS';

Modules - default exports & imports

// meetup.js
export const BEST_MEETUP = 'ParisJS';
export default function speak(s) { console.log(s); };
// main.js
import * as meetup from './meetup.js';
meetup.speak(meetup.BEST_MEETUP); // 'ParisJS';
// main2.js
import speak from './meetup.js';
speak('Hello'); // 'Hello';

Classes

A feature everyone wanted! (not)

class Plane extends Vehicle {
   constructor(name, capacity) {
    super(name); 
    this.capacity = capacity;
   }
   announce() {
     console.log(super.announce());
     console.log('I can carry ' + this.capacity + ' people');
   }
   static explainTheUse () {
     console.log('I CAN FLY! YOU CAN FLY! WE CAN FLY!')
   }
}

for...of

Our new loop overlord. Iterates on arrays and anything that implements iterators

for (let value of [1,2,3]) {
  console.log(value); // 1, 2, 3
}
for (let [index, value] of ['a', 'b', 'c'].entries()) {
  console.log(index, value); // 0 a, 1 b, 2c
}

Sets

Basically arrays with a unicity enforcement

Iterate with for...of!

var a = new Set([1,2,3,4,3,2,1,0,1])
console.log(a); // Set [ 1, 2, 3, 4, 0 ]
for (let i of a) {
  console.log(i); // 1 2 3 4 0
}

Maps

Adios, if (object.hasOwnProperty)

Can take any kind of value (string, object, number...) as key

Easy to get its length

Iterate with for...of!

var meetups = new Map();

meetups.set('ParisJS', { location: 'SenseSpace', edition: 47 });
meetups.set(NaN, { location: 'SecretSpace' });

for (let [name, infos] of meetups.entries()) {
  console.log(`Meetup: ${name}, location: ${infos.location}`)
}
meetups.get('ParisJS');
meetups.get(NaN);

Generators

function* simpleGenerator(){
  yield "first";
  yield "second";
  for (var i = 0; i < 2; i++) {
    yield i;
  }
}

var g = simpleGenerator();
console.log(g.next()); // { value: "first", done: false }
console.log(g.next()); // { value: "second", done: false }
console.log(g.next()); // { value: 0, done: false }
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: undefined, done: true }

Promises

function foobar() {
  return new Promise(function(resolve, reject) {
    return Math.random() > 0.5 ?
      resolve(':)') : reject(new Error(':('));
  });
}

foobar()
.then((foo) => console.log('Success! ' + foo))
.catch((bar) => console.log('Failure! ' + bar));
// No .finally for now :(

new utility functions

People are getting sick of indexOf

'ParisJS'.includes('JS');
['ParisJS', 'Pizzas', 'Soon'].find(el => el === 'Soon');
['ParisJS', 'Pizzas', 'Soon'].findIndex(el => el === 'Soon');

new utility functions

Object.assign({}, { name: 'ParisJS' }, { edition: 47 } );
Array.from(document.querySelectorAll('*'));

...

And more...

ES2016 (ES7)

async functions

The Holy Grail: better than promises

async function doAsyncOp () {
  val = await asynchronousOperation();
  val = await asynchronousOperation(val);
  val = await asynchronousOperation(val);
  return await asynchronousOperation(val);
}

ES2017 (ES8)

So

ECMAScript 2015 has WAY TOO MUCH new stuff

All the more reason to start using things right now if you don't already

Either you wait a lot, or you'll end up using a transpiler anyway.

Plus, if you don't, I'll come back with this same presentation renamed

"Why aren't you yet using ECMAScript 2015?"

And I'll keep talking while the pizzas get cold.

Resources

Thank you

Any questions?

This: http://hugo-agbonon.github.io/presentations/es2015