Ecmascript 6 and Babel
Course division
- Introduction
- ES6 and Babel
- ES2016
Part 1
Introduction
- What/Why ES6?
- ES6 vs ES2016
- Babel
What is ES6?
- 6th release of ECMAScript
- ECMAScript == Javascript
- ECMA International
- ES6 == ES2015 == Harmony
More about history:
http://benmccormick.org/2015/09/14/es5-es6-es2016-es-next-whats-going-on-with-javascript-versioning/
Versions
ES1 | 1997 |
ES2 | 1998 |
ES3 | 1999 |
ES4 | Abandoned |
ES5 | 2009 |
ES6 | 2015 |
ES7 | 2016 |

ES6 in the browser

ES6 in Node.js
Why ES6?
- Easier Development
- Easier Migrations
- Future Proof
Easier Development
- Writing code more efficiently
- More readable code
- JS now used on backend too
- Using standard conventions
ES5
var link = function (n, color, url) {
var n = n || 50;
var color = color || 'red';
var url = url || 'foo.co';
...
}
ES6
var link = function (n=50, color='red', url='foo.co') {
}
ES5
var body = req.body,
username = body.username,
password = body.password;
ES6
var {username, password} = req.body;
Easier Migrations
- Angular 2 and libraries are in ES6
- React + Redux
- Decoupling from Angular
Decoupling from Angular
- ES6 Module System vs Angular Modules
- Services and Controllers as Classes
Future proof
- Libraries and Companies
- Browsers
- Developer Support
Who's using ES6 today
- Angular 2.0
- Ember
- React
- Netflix
- ...
ES6 Native Browser Support

Developers Support
- ES6 is what new developers will be (are) using
- Avoid technical debt
- ES6 is more fun to write
- Improved tooling around ES6
ES6 vs ES2016
- ES2016 == ES7
- Features released as they are approved
- Proposals
- 4 stages for approval
TC39 open proposals:
http://github.com/tc39/ecma262
ES6
var [a, b, ...rest] = [1, 2, 3, 4];
console.log(rest) // 3,4
ES7
var {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4};
console.log(JSON.stringify(rest)) // {c: 3, d: 4}
Babel
- Javascript compiler
- Used as a build step
- Transforms ES6/ES7 in ES5
in.js
[1, 2, 3].map(n => n + 1);
out.js
[1, 2, 3].map(function(n) {
return n + 1;
});
=>
Babel
also
- Supports JSX
- Built out of plugins
- Used by facebook, mozilla, npm...
Part 2
ES6 and Babel
- ES6 features
- ES6 in JS frameworks
- Babel
- let
- const
- Destructuring
- Default
- Template strings
- Rest parameters
- Spread
- Arrows
- Enhanced object literals
- Classes
- Promises
- for..of
ES6 features
- Unicode
- Module loaders
- Map / Set
- Proxies
- Symbols
- Subclassable Built-ins
- Primitive types APIs
- Binary and Octal Literals
- Reflect API
- Iterators / Generators
What we won't cover
You can learn them on:
https://babeljs.io/docs/learn-es2015/
let
// ES5
if (userCreated) {
var successMsg = "Welcome!";
}
console.log(successMsg); // Welcome!
// ES6
if (userCreated) {
let successMsg = "Welcome!";
}
console.log(successMsg); // ReferenceError: successMsg is not defined
// ES5
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // Prints 9
// ES6
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // ReferenceError: i is not defined
Block
Scope
Lexical
Environment
const
let x; // x === undefined
const z; // SyntaxError: const declarations must have an initializer
const y = 10;
y = 20; // SyntaxError: Assignment to constant variable
const o = {};
o.a = 10; // ok!
Read
Only
Used
whenever possible
let / const
- Block-scoped
- Keep code simple and readable
- var still exists
Destructuring
let [x, y, z] = [1, 2, 3];
// is equivalent to...
let x = 1, y = 2, z = 3;
let [x, y] = [1, 2];
console.log(x, y); // 1, 2
[x, y] = [y, x]; // Swap the values of x and y
console.log(x, y); // 2, 1
let [x, [y]] = [1, [2]]; // Nested arrays
console.log(x, y); // 1, 2
Easily
access
arrays
elements
Destructuring
let { a: x, b: y } = { a: 1, b: 2 };
console.log(x, y); // 1, 2
let { a: x, b: { c: y } } = { a: 1, b: { c: 2 } }; // Nested objects
console.log(x, y); // 1, 2
// Using for multiple return values
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
console.log(a, b, c); // 1, 2, 3
Easily
access
objects
elements
Default
// ES5
function multiply(x, y) {
y = y || 1; // Default to 1 if falsy
return x * y;
}
// ES6
function multiply(x, y = 1) {
return x * y;
}
// Reference args to the left
(function example(x, y = x * 2) {
console.log(x, y); // 2, 4
}(2));
Template strings
// Interpolate variable bindings
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?` // Hello Bob, how are you today?
// Multiline strings
`In ES5 this
is
not legal.`
Arrows
// ES5
function square(x) {
return x * x;
};
// ES6
const square = (x) => {
return x * x;
};
// Simplifying
const square = (x) => (
x * x;
);
// Simplifying even more
const square = x => x * x;
Less
Verbose
More
Readable
Arrows
const arr = [1, 2, 3];
// ES5
var squares = arr.map(function (x) { return x * x });
// ES6
let squares = arr.map(x => x * x);
// ES5
var reduxMiddleware = function(store) {
return function(next) {
return function(action) {
return next(action)(store);
}
}
}
// ES6
let reduxMiddleware = store => next => action => {
return next(action)(store);
};
Less
Verbose
More
Readable
Arrows
// ES5
function UiComponent() {
var button = document.getElementById('myButton');
var self = this;
button.addEventListener('click', function() {
console.log('CLICK');
self.handleClick();
});
}
// ES6
function UiComponent() {
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('CLICK');
this.handleClick(); // lexical `this`
});
}
// Also lexical
arguments
super
new.target
Lexical
this
No binding
needed
Exercise
function pow(base, exponent) {
var result = 1;
var exponent = exponent || 2;
for (var i = 0; i < exponent; i++) {
result = result * base;
}
return result;
}
function printPow(numbers) {
var result = pow(numbers.base, numbers.exponent);
console.log("result: " + result);
}
printPow({base: 2, exponent: 3}); // => 8
Use your new powers to transform the code below into ES6
Exercise
const pow = (base, exponent = 2) => {
let result = 1;
for (let i = 0; i < exponent; i++) {
result = result * base;
}
return result;
};
const printPow = ({base, exponent}) => {
const result = pow(base, exponent);
console.log(`result: ${result}`);
};
printPow({base: 2, exponent: 3}); // => 8
Use your new powers to transform the code below into ES6
Answer
arrow
arrow
default
let
const
destructuring
template strings
Rest parameters
// ES5
function logEach() {
var things = Array.prototype.slice.call(arguments);
things.forEach(function (thing) {
console.log(thing);
});
}
logEach("a", "b", "c");
// ES6
function logEach(...things) {
things.forEach(function (thing) {
console.log(thing);
});
}
logEach("a", "b", "c");
Spread
// ES5
function example(a, b, c) {
console.log(a, b, c); // 1, 2, 3
}
var args = [1, 2, 3];
example.apply(null, args);
// ES6
function example(a, b, c) {
console.log(a, b, c); // 1, 2, 3
}
let args = [1, 2, 3];
example(...args);
let parts = ["shoulder", "knees"];
let lyrics = ["head", ...parts, "toes"]; // ["head", "shoulder", "knees", "toes"]
Enhanced Object Literals
var obj = {
// __proto__
__proto__: theProtoObj,
// Does not set internal prototype
'__proto__': somethingElse,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ "prop_" + (() => 42)() ]: 42
};
Closer to class declarations
Benefit
from OOP
for..of
for (let value of [2,3,7]) {
console.log(value);
}
// 2
// 3
// 7
for (let value of "foo") {
console.log(value);
}
// "f"
// "o"
// "o"
for (let i in [2,3,7]) {
console.log(i);
}
// 0
// 1
// 2
Iterate over any iterable
Iterables can be created
More powerfull than for..in
Exercise
function giveSuperPowers(hero) {
var specialPowers = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < specialPowers.length; i++) {
console.log("Adding " + specialPowers[i] + "!");
}
return {
name: hero.name,
speed: hero.speed * 3,
specialPowers: specialPowers,
run: function() {
console.log("Running!");
}
};
}
var luke = { name: "Luke", speed: 3 };
var superLuke = giveSuperPowers(luke, "XRay", "Invisibility", "Teleport");
Use the latest features you've learned to transform the code below into ES6
Exercise
const giveSuperPowers = ({name, speed}, ...specialPowers) => {
for (let specialPower of specialPowers) {
console.log(`Adding ${specialPower}!`);
}
return {
name,
speed: speed * 3,
specialPowers,
run() {
console.log("Running!");
}
};
};
const luke = { name: "Luke", speed: 3 };
const superLuke = giveSuperPowers(luke, "XRay", "Invisibility", "Teleport");
Use the latest features you've learned to transform the code below into ES6
Answer
let
arrow
for..of
template strings
enhanced object literals
Rest parameters
const
Destructuring
Classes
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
//...
}
update(camera) {
//...
super.update();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
const geometry = 6.7;
const materials = ['trace', 'config'];
skinnedMesh = new SkinnedMesh(geometry, materials);
Syntactic sugar over JS
prototype-based OO
Exercise
var ExampleComponent = React.createClass({
render: function() {
return (
<div onClick={this._handleClick}>
Hello, world.
</div>
);
},
_handleClick: function() {
console.log(this);
}
});
Convert the following React component to an ES6 Class.
Use React.Component as your base class.
Exercise
class ExampleComponent extends React.Component {
render() {
return (
<div onClick={this._handleClick}>
Hello, world.
</div>
);
}
_handleClick() {
console.log(this);
}
}
Convert the following React component to an ES6 Class.
Use React.Component as your base class.
Answer
Promises
// An immediately resolved promise
let p = Promise.resolve("foo");
// Can get it after the fact, unlike events
p.then((res) => console.log(res));
let p2 = new Promise(function(resolve, reject) {
setTimeout(() => resolve(5), 2000);
});
// Handler can't change promise, just value
p2.then((res) => {
res += 2;
console.log(res);
});
// Still gets 4
p2.then((res) => console.log(res));
Async programming
Used by many JS libs
Modules
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
// Import complete module:
//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
Modules
// There can be a single default export. For example, a function:
//------ myFunc.js ------
export default function () { ··· } // no semicolon!
//------ main1.js ------
import myFunc from 'myFunc';
myFunc();
// Or a class:
//------ MyClass.js ------
export default class { ··· } // no semicolon!
//------ main2.js ------
import MyClass from 'MyClass';
const inst = new MyClass();
Modules
- Similarly to CommonJS: they have a compact syntax, a preference for single exports and support for cyclic dependencies.
- Similarly to AMD: they have direct support for asynchronous loading and configurable module loading.
Exercise
var fruits = require("./fruits");
var blend = require("./blend");
var makeRedJuice = function() {
return blend(fruits.strawberry, fruits.raspberry, fruits.plum);
};
module.exports = makeRedJuice;
Transform the following CommonJS snippet using ES6 modules
Exercise
import { strawberry, raspberry, plum } from "./fruits";
import blend from "./blend";
export default function() {
return blend(strawberry, raspberry, plum);
};
Transform the following CommonJS snippet using ES6 modules
Answer
ES6 in JS frameworks
- React
- Redux
- AngularJS
- Backbone.js
ES6 in React

Modules
consts
Class and inheritance
constructor
super
destructuring
ES6 in Redux

Destructuring
Enhanced object literals
Enhanced object literals
ES6 in AngularJS

Template strings
Controllers as classes
Services in constructor
ES6 in Backbone.js


Classes are everywhere!
Babel

in.js
[1, 2, 3].map(n => n + 1);
out.js
[1, 2, 3].map(function(n) {
return n + 1;
});
=>
Babel
Babel CLI
$ npm install --global babel-cli
Babel CLI: simple way to compile files from the command line
$ babel my-file.js
We can compile it like so:
$ babel example.js -o compiled.js
To output to a file:
Babel CLI
$ npm install --save-dev babel-cli
Babel CLI locally:
- Different projects / Babel versions, same machine
- Portable project and easier to setup
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"build": "babel src -d lib"
},
"devDependencies": {
"babel-cli": "^6.0.0"
}
}
package.json
Plugins and Presets
Configuring Babel:
- Running babel alone just copy files around
- plugins specify to Babel what to do
- presets are groups of plugins
{
"presets": [],
"plugins": []
}
.babelrc
Plugins and Presets
$ npm install --save-dev babel-preset-es2015
babel-preset-es2015
Gathers plugins for all ES2015 transformations
(compiles ES6 to ES5)
Install
{
"presets": [
"es2015"
],
"plugins": []
}
.babelrc
Plugins and Presets
$ npm install --save-dev babel-preset-react
babel-preset-react
Gathers plugins for all React transformations
Install
{
"presets": [
"react"
],
"plugins": []
}
.babelrc
Plugins and Presets
$ npm install --save-dev babel-preset-stage-2
babel-preset-stage-x
- Follows the JS stages standard through the TC39's process
- Each stage (0-4) requires all its precedent stages
Install (example)
{
"presets": [
"stage-2"
],
"plugins": []
}
.babelrc
Babel with Gulp
$ npm install --save-dev gulp-babel babel-preset-es2015
Install
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('default', () => {
return gulp.src('src/app.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('dist'));
});
Usage
$ npm install --save-dev grunt-babel babel-preset-es2015
Install
require('load-grunt-tasks')(grunt); // npm install --save-dev load-grunt-tasks
grunt.initConfig({
babel: {
options: {
sourceMap: true,
presets: ['es2015']
},
dist: {
files: {
'dist/app.js': 'src/app.js'
}
}
}
});
grunt.registerTask('default', ['babel']);
Usage
Babel with Grunt
Babel with Webpack
npm install babel-loader babel-core babel-preset-es2015 --save-dev
Install
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
query: {
presets: ['es2015']
}
}
]
}
Usage
Part 3
ES2016
- ES2016 features
- ES2016 in real world
- Array.prototype.includes
- Exponentiation operator
- Rest / Spread in objects
- Decorators
ES2016 features
- Async / Await functions
- Class static properties
- Instance fields
Array.prototype.includes
['a', 'b', 'c'].includes('c');
// <- true
[{}, {}].includes({}); // strictly a reference comparison
// <- false
var a = {};
[{}, a].includes(a);
// <- true
// Using fromIndex param
['a', 'b', 'c', 'd'].includes('b', 2);
// <- false
Exercise
const a1 = ['a', 'b', 'c'];
const a2 = ['d', 'y', 'a', 't', 'c', 'c'];
whichIncluded(a1, a2); // => [false, false, true, false, true, true];
Write a function that takes two arrays and returns an array of booleans telling which elements of the second array are included in the first one. Example:
Exercise
const whichIncluded = (a1, a2) => a2.map(v => a1.includes(v));
Write a function that takes two arrays and returns an array of booleans telling which elements of the second array are included in the first one.
Answer
Exponentiation operator
2 ** 3
// <- 8
1 ** 2 === Math.pow(1, 2)
// <- true
let a = 2;
a **= 3; // equivalent to a = Math.pow(a, 3)
console.log(a);
// <- 8
Rest/Spread in objects
// Rest
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
// Spread
let n = { x, y, ...z };
n; // { x: 1, y: 2, a: 3, b: 4 }
Exercise
sumObj({ v1: 1, v2: 2, v3: 3 }); // => 6
Write a function that takes an object and returns the sum of the squares of its properties named base1 and base2 plus the sum of all its other elements.
You can use the following function, which returns the sum of all the object's values
specialSum({ base1: 3, base2: 3, value1: 7 }); // => 25
specialSum({ base1: 2, base2: 3, value1: 3, value2: 4 }); // => 20
Exercise
Write a function that takes an object and returns the sum of the squares of its properties named base1 and base2 plus the sum of all its other elements.
const specialSum = ({base1, base2, ...rest}) => {
return base1 ** 2 + base2 ** 2 + sumObj(rest);
}
Solution
Decorators
class Cat {
meow() { return `${this.name} says Meow!`; }
}
Evaluating this class results in installing the meow function onto `Cat.prototype`, roughly like this:
Object.defineProperty(Cat.prototype, 'meow', {
value: specifiedFunction,
enumerable: false,
configurable: true,
writable: true
});
Imagine we want to mark a property or method name as not being writable.
function readonly(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
Decorators
We can then add it to our meow property as follows:
class Cat {
@readonly
meow() { return `${this.name} says Meow!`; }
}
Now, before installing the descriptor onto `Cat.prototype`, the engine first invokes the decorator:
let descriptor = {
value: specifiedFunction,
enumerable: false,
configurable: true,
writable: true
});
// The decorator has the same signature as Object.defineProperty and has an
// opportunity to intercede before the relevant defineProperty actually occurs
descriptor = readonly(Cat.prototype, 'meow', descriptor) || descriptor;
Object.defineProperty(Cat.prototype, 'meow', descriptor);
Decorators
function readonly(target, name, descriptor){
descriptor.writable = false;
return descriptor;
}
function deprecate(target, name){
console.warn(`${name} is deprecated`);
return false;
}
class Person {
@readonly
name() { return `${this.first} ${this.last}` }
@deprecate
age() { return `${this.age}` }
}
Extend function behavior
Keep function internals
Decorators
function superhero(target) {
target.isSuperhero = true;
target.power = 'flight';
}
@superhero
class MySuperHero() {}
console.log(MySuperHero.isSuperHero); // true
Extend class behavior
Keep class internals
Decorators
- Higher-order functions
- github.com/jayphelps/core-decorators.js
- Used in many JS frameworks
Learn more:
https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.ootqplafi
Exercise
class Pikachu {
useTackle() { console.log('Pikachu used tackle!'); }
@superEffective
useThunderbolt() { console.log('Pikachu used thunderbolt!'); }
}
myPikachu = new Pikachu();
myPikachu.useTackle();
// Pikachu used tackle!
myPikachu.useThunderbolt();
// Pikachu used thunderbolt!
// ...and it's super effective!!
Create a decorator function that behaves like so:
Exercise
function superEffective(target, name, descriptor){
const func = descriptor.value;
descriptor.value = function() {
func();
console.log("...and it's super effective!!");
};
return descriptor;
}
Solution
Create a decorator function that behaves like so:
// ES6
function doAsyncOp () {
return asynchronousOperation().then(function(val) {
console.log(val);
return val;
});
};
// ES7
async function doAsyncOp () {
let val = await asynchronousOperation();
console.log(val);
return val;
};
console.log('before')
doAsyncOp();
console.log('after');
// Suppose asynchronousOperation is a setTimeout:
// "before"
// "after"
// val
Async / Await functions
async function getUser () {
console.log("Request initiated...");
const user = await http.get("/user");
console.log("Request complete!");
return user;
};
async function getUserAndPrintName() {
const user = await getUser();
console.log(user.name);
};
getUserAndPrintName();
console.log("Do some other thing");
// Request initiated...
// Do some other thing
// Request complete!
// User name: Amir
Async / Await functions
Async / Await functions
// ES6
function loadStory() {
return getJSON('story.json').then(function(story) {
addHtmlToPage(story.heading);
return story.chapterURLs.map(getJSON)
.reduce(function(chain, chapterPromise) {
return chain.then(function() {
return chapterPromise;
}).then(function(chapter) {
addHtmlToPage(chapter.html);
});
}, Promise.resolve());
}).then(function() {
addTextToPage("All done");
}).catch(function(err) {
addTextToPage("Argh, broken: " + err.message);
}).then(function() {
document.qSelector('.spinner').style.display = 'none';
});
}
// ES7
async function loadStory() {
try {
let story = await getJSON('story.json');
addHtmlToPage(story.heading);
for (let chapter of story.chapterURLs.map(getJSON)) {
addHtmlToPage((await chapter).html);
}
addTextToPage("All done");
} catch (err) {
addTextToPage("Argh, broken: " + err.message);
}
document.qSelector('.spinner').style.display = 'none';
}
Class static properties
class MyClass {
static myStaticProp = 42;
constructor() {
console.log(MyClass.myStaticProp); // Prints '42'
}
}
Instance fields
class MyClass {
myProp = 42;
constructor() {
console.log(this.myProp); // Prints '42'
}
}
Exercise
async function getUser () {
console.log("Request initiated...");
const user = await http.get("/user");
console.log("Request complete!");
return user;
};
async function getUserAndPrintName() {
const user = await getUser();
console.log(user.name);
};
getUserAndPrintName();
console.log("Do some other thing");
// Request initiated...
// Do some other thing
// Request complete!
// User name: Amir
Be a human compiler and transform the code below we've seen into ES6
Exercise
function getUser () {
console.log("Request initiated...");
return http.get("/user").then(function(user) {
console.log("Request complete!");
return response;
});
}
function getUserAndPrintName() {
getUser().then(function(user) {
console.log(user.name);
});
};
getUserAndPrintName();
console.log("Do some other thing");
Solution
Be a human compiler and transform the code below we've seen into ES6
ES2016 in real world

Decorators
Object spreads
Class static properties
Instance fields
Instance fields
$ npm install --save-dev babel-preset-stage-0
Compiling with Babel
Babel stages presets (babel-preset-stage-x) are used to compile features still in process of being accepted in the next standard (ES2016)
Install (example)
{
"presets": [
"stage-0"
],
"plugins": []
}
.babelrc
ES2016 in real world
Learn more
- exploringjs.com
- leanpub.com/understandinges6
- 2ality.com
- babeljs.io/docs/learn-es2015
Ecmascript 6 and Babel - backup
By guilhermesad
Ecmascript 6 and Babel - backup
- 1,009