KEMBAR78
Idiomatic Javascript (ES5 to ES2015+) | PDF
Idiomatic JavascriptIdiomatic Javascript
From ES5 => ES6
A Brief History of Time...A Brief History of Time...
A Brief History of Time...A Brief History of Time...
Official name of the language is ECMAScript
ECMA is the Standardizations Body
TC39 is the committee working on the
standards.
in 2015, ECMA decided to do yearly standards,
hence the renaming.
ES6 Browser SupportES6 Browser Support
Current browser support for ES6 is great on the desktop -
not so much elsewhere
http://kangax.github.io/compat-table/es6/
Current development uses ES6/next features
through the use of transpilers like Babel
Arrow FunctionsArrow Functions
Arrows are a function shorthand using the => syntax. They are
syntactically similar to the related feature in C#, Java 8 and
CoffeeScript. They support both expression and statement
bodies. Unlike functions, arrows share the same lexical this as
their surrounding code.
Arrow Functions
var list = [1,2,3,4,5];
list.map(function(n) {
return n * 2;
}, this);
list.map(function(n) {
return n * 2;
}.bind(this));
In ES5, retaining the context of this in function expressions
was typically done via Function#bind(); or through passing an
execution context those few standard functions that allowed
one.
var list = [1,2,3,4,5];
list.map(n => n * 2);
ES5ES5 ES6ES6
Arrow Functions
// Lexical this
var brendan = {
_name: 'Brendan Eich',
_languages: ['assembly','javascript','C'],
logLanguages: function() {
this._languages.forEach(function (lang) {
return console.log(this._name + ' knows ' + lang);
}, this);
}
};
const brendan = {
name: 'Brendan Eich',
languages: ['assembly','javascript','C'],
logLanguages: () => this.languages.forEach(lang =>
console.log(`${this.name} knows ${lang}`)
);
};
ES5ES5
ES6ES6
Block ScopingBlock Scoping
Block-scoped binding constructs. let is the new var.
 const is single-assignment. Static restrictions
prevent use before assignment.
Block Scoping
var a = 5;
var b = 10;
if (a === 5) {
// IIFE !!!
(function () {
var a = 4;
b = 1;
console.log(a); // 4
console.log(b); // 1
})();
}
console.log(a); // 5
console.log(b); // 1
ES5 required IIFEs in order to create pseudo-block scoping.
ES6 gives us let, which is scoped to the enclosing block.
var a = 5;
var b = 10;
if (a === 5) {
let a = 4; // scope inside if-block
var b = 1; // scope inside function
console.log(a); // 4
console.log(b); // 1
}
console.log(a); // 5
console.log(b); // 1
ES5ES5 ES6ES6
Block Scoping
// define as a non-writable `constant`
// and give it a value
Object.defineProperties(window, {
pi: {
value: 3.14159265359,
enumerable: true,
writable: false
}
});
// var pi = 7;
// Attempt to overwrite the constant
pi = 15;
console.log('Slice of pi: ' + pi);
// 3.14159265359
const pi = 3.14159265359;
// Attempt to overwrite the constant
pi = 15;
// TypeError: Assignment to constant
console.log('Slice of pi: ' + pi);
// 3.14159265359
// Never executes...
ES5ES5 ES6ES6
String TemplatesString Templates
Template strings provide syntactic sugar for constructing
strings. This is similar to string interpolation features in
Perl, Python and more. Optionally, a tag can be added to
allow the string construction to be customized, avoiding
injection attacks or constructing higher level data
structures from string contents.
String Templates
var name = 'Dan';
var dan = {
projects: ['redux','react-dnd']
};
// concatenation
console.log(name + ' Abramov');
//=> Dan Abramov
// joining
console.log(
['Known for ', dan.projects[0]].join('')
);
//=> Known for redux
ES5 had nothing similar. You would just concatenate strings
with expressions.  ES6 allows interpolation of variables,
expressions and functions inside template strings.
ES5ES5
String Templates
const name = 'Dan';
const n = 10;
const dan = {
projects: ['redux','react-dnd']
};
const fn = () => 'reducers';
// variables
console.log(`${name} Abramov`);
// objects
console.log(`Known for ${dan.projects[0]}`);
// expression interpolation
console.log(`${n} + 2 = ${n + 2}`);
// functions
console.log(`I love ${fn()}`);
ES6ES6
String Templates
// Multiline strings
// 1. escaping - white space retained
// 2. concatenation
console.log(
'This string spans n
multiple lines. It's crazy!n' +
'It's a bit harder to read'
);
//=> This string spans
//=> multiple lines. It's crazy!
//=> It's a bit harder to read
ES5ES5
// Multiline strings
// - white space retained
console.log(
`This string spans
multiple lines. It's crazy!`
);
//=> This string spans
//=> multiple lines. It's crazy!
ES6ES6
Object PropertiesObject Properties
Object Initializer Shorthand
Object Method Assignment
Computed Properties
Object literals are extended to support setting the
prototype at construction, shorthand for foo: foo
assignments, defining methods and making super calls.
Together, these also bring object literals and class
declarations closer together, and let object-based design
benefit from some of the same conveniences.
Object Properties
function getPoint() {
var x = 1;
var y = 10;
return { x: x, y: y };
}
getPoint();
//=> { x: 1, y: 10 }
With property shorthand notation, if the property name and
value variable are the same, no need to repeat yourself.
function getPoint() {
var x = 1;
var y = 10;
return { x, y };
}
getPoint()
//=> { x: 1, y: 10 }
ES5ES5 ES6ES6
Object Properties
var object = {
value: 42,
toString: function toString() {
return this.value;
}
};
object.toString() === 42;
// -> true
With object method assignment shorthand you can shorten
method declarations on objects/classes as well.
var object = {
value: 42,
toString() {
return this.value;
}
};
console.log(object.toString() === 42);
// -> true
ES5ES5 ES6ES6
Object Properties
var prefix = 'foo';
var obj = {};
obj[prefix + 'bar'] = 'hello';
obj[prefix + 'baz'] = 'world';
console.log(obj['foobar']);
// -> hello
console.log(obj['foobaz']);
// -> world
With ES6 we now have the ability to use computed property
names as well. You can evaluate any expression within [  ].
var foo = 'foo';
var fn = () => 'foo';
var obj = {
[foo + 'bar']: 'hello',
[fn() + 'baz']: 'world'
};
console.log(obj['foobar']);
// -> hello
console.log(obj['foobaz']);
// -> world
ES5ES5 ES6ES6
Destructuring AssignmentsDestructuring Assignments
Destructuring allows binding using pattern matching,
with support for matching arrays and objects.
Destructuring is fail-soft, similar to standard object
lookup foo["bar"], producing undefined values when not
found.
Destructuring
var foo = { bar: 'Kyle', baz: 'Simpson' };
var bar = foo[bar];
var baz = foo[baz];
// -> bar: 'Kyle', baz 'Simpson'
var list = [1,2,3];
var one = list[0];
var two = list[1];
var three = list[2];
// -> one: 1, two: 2, three: 3
Binds the values from one Array or Object to another.
const foo = { bar: 'Kyle', baz: 'Simpson' };
const {bar, baz} = foo;
// -> bar: 'Kyle', baz 'Simpson'
const list = [1,2,3];
const [one, two, three] = list;
// -> one: 1, two: 2, three: 3
ES5ES5
ES6ES6
Destructuring
You can also map destructured objects to aliases as well.
const foo = { bar: 'Kyle', baz: 'Simpson' };
const { bar: a, baz: b } = foo;
// -> bar: 'Kyle', baz 'Simpson'
ES6ES6
Destructuring
Or even pull out deeply nested properties 
const person = {
name: 'Steve',
things: { one: 1, two: 2 },
years: [1975, 1995, 2015]
};
const { name, things: { one }} = person;
// -> name: Steve
// -> one: 1
// But, if it's not there
const stuff = { one: 1, two: 2 };
const { three } = stuff;
// -> three: undefined
ES6ES6
Destructuring
Plus, it makes it easier to do things like swapping variables
without using an auxiliary. Or pulling out properties
dynamically using computed property names.
let a = 10, b = 20;
[a, b] = [b, a];
// -> a = 20, b = 10
const key = 'doge';
const { [key]: foo } = { doge: 'such bar!' };
// -> foo = such bar!
// Assign defaults (in case of undefined)
const wow = { such: 'awesome' };
const { much='missing' } = wow;
// -> much = missing
// Skip over elements in arrays
let [,,c,d] = [1,2,3,4,5];
// -> c = 3
// -> d = 4
ES6ES6
Function ArgumentsFunction Arguments
Default Arguments
Spread
Rest
Callee-evaluated default parameter values. Turn
an array into consecutive arguments in a function
call. Bind trailing parameters to an array. Rest
replaces the need for arguments and addresses
common cases more directly.
Default Argument Values
function iam(name) {
(name === undefined) && (name="Batman");
console.log("I am " + name + '!');
}
iam();
// -> I am Batman!
Similar to the default assignments used in destructuring,
functions allow you assign default values as well. If the
parameter passed is undefined, it gets the default.
function iam(name="batman") {
console.log(`I am ${name}!`);
}
iam();
// -> I am Batman!
ES5ES5
ES6ES6
Defaults & Destructuring
You can even use destructuring and defaults on function
arguments 
function random ({ min=1, max=300 }) {
return Math.floor(Math.random() * (max - min)) + min;
}
random({});
// -> 174
random({max: 24});
// -> 18
// Or, make the whole argument optional
function random ({ min=1, max=300 }={}) {
return Math.floor(Math.random() * (max - min)) + min;
}
random();
// -> 133
ES6ES6
The spread operator pulls individual items out of a collection
(Array or Object).
function reducer(state={}, action) {
switch(action.type) {
case 'SET_AGE': return {
...state,
age: action.age
};
default:
return state;
}
}
const state = { name: 'Dave', age: 40 };
const action = {
type: 'SET_AGE',
age: 41
};
reducer(state, action);
// -> { name: 'Dave', age: 41 }
ES6ES6
... spread operator
var nums = [4,1,9,5];
Math.max.apply(null, nums);
// -> 9
let a = [1,2,3];
let b = [4,5,6];
// join
var c = a.concat(b);
// -> c = [1,2,3,4,5,6]
// copy
var d = [].slice.call(c, 0);
// -> d = [1,2,3,4,5,6]
// splice
var e = [0,7,8];
var f = e.slice(0,1)
.concat(c, e.slice(1), [9,10]);
// -> f = [0,1,2,3,4,5,6,7,8,9,10]
Works with Arrays as well (non-mutating).
let nums = [4,1,9,5];
Math.max(...nums);
// -> 9
let a = [1,2,3];
let b = [4,5,6];
// join
let c = [...a, ...b];
// -> c = [1,2,3,4,5,6]
// copy
let d = [...c];
// -> d = [1,2,3,4,5,6]
// splice
let e = [0, ...d, 7, 8, ...[9,10]];
// -> e = [0,1,2,3,4,5,6,7,8,9,10]
ES5ES5 ES6ES6
... spread operator
function join(sep /*, ...args*/) {
var args = [].slice.call(arguments, 1);
return args.join(sep);
}
join(', ', 'john', 'bobby', 'ted')
// -> 'john, bobby, ted'
The rest operator (or, gather) allows us to pull values into a
collection Array or Object.
const join = (sep, ...args) => args.join(sep);
join(':', "one", "two", "three");
// -> one:two:three
ES5ES5
ES6ES6
... rest operator
You can even use it with destructuring to gather values.
var list = [1,2,3,4,5];
var [head, ...tail] = list;
// -> head = 1
// -> tail = [2,3,4,5]
var list = [1,2,3,4,5];
var [head, ...tail] = list;
console.log(head, tail);
var passed = {
className: 'panel',
style: { color: '#369'},
title: 'Panel',
active: true
};
var { className, style, ...props } = passed;
// -> className = 'panel'
// -> styles = { color: '#369' }
// -> props = { title: 'Panel', active: true }
ES6ES6
... rest operator
Iterators & ArraysIterators & Arrays
Iterators allow us to traverse a collection. Generalize for..in
to custom iterator-based iteration with for..of. Array#from
allows us to convert array-like collections into real arrays.
Iterators & Arrays
var a = [1,2,3];
a.forEach(function (element) {
console.log(element);
});
// -> 1 2 3
// Using a for loop
var a = [1,2,3];
for (var i = 0; i < a.length; ++i) {
console.log(a[i]);
}
// -> 1 2 3
// Uses an iterator behind the scenes
for (let element of [1, 2, 3]) {
console.log(element);
}
// => 1 2 3
ES5ES5
ES6ES6
Iterators
function iteratorFor(list) {
var i = 0;
return {
next: function() {
return {
value: list[i++],
done: i > list.length
};
}
}
}
var iter = iteratorFor([1,2,3]);
var res = iter.next();
while (!res.done) {
console.log(res);
res = iter.next();
}
// -> Same output as right-side
What is an iterator?  ES6 let's us access them via predefined
Symbol properties. 
let iter = [1, 2, 3][Symbol.iterator]();
console.log(iter.next());
// -> {value: 1, done: false}
console.log(iter.next());
// -> {value: 2, done: false}
console.log(iter.next());
// -> {value: 3, done: false}
console.log(iter.next());
// -> {value: undefined, done: true}
ES5ES5 ES6ES6
Iterators with Generators
You can write your own iterators using ES6 generator
functions and yield. 
function* iteratorFor(list) {
for (let item of list) {
yield item;
}
}
const iter = iteratorFor([1,2,3]);
for (let value of iter) {
console.log(value);
}
// -> 1 2 3
// can't use iter again
let iter2 = iteratorFor([1,2,3]);
console.log([...iter2]);
// -> [1,2,3]
ES6ES6
ClassesClasses
ES2015 classes are a simple sugar over the
prototype-based OO pattern. Having a single,
convenient, declarative form makes class patterns
easier to use, and encourages interoperability.
Classes support prototype-based inheritance, super
calls, instance and static methods and constructors.
// Person "Class"
function Person(name) {
this.name = name;
}
Person.type = 'person';
Person.prototype.greet = function() {
return 'Hello, my name is ' + this.name + '.';
}
Person.prototype.typeOf = function() {
return this.constructor.type;
}
// Employee "Class"
function Employee(company, name) {
Person.call(this, name);
this.company = company;
}
Employee.type = 'employee';
// setup inheritance via prototype chain
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
// Override greet method
Employee.prototype.greet = function() {
return Person.prototype.greet.call(this) +
' I work at ' + this.company
}
ES5ES5
ES5 "Classes"
// create an instance
var Dave = new Employee('OCI', 'David');
// call a method
Dave.greet();
// -> Hello, my name is David. I work at OCI
// access "static" property via method
console.log('Dave is an ' + Dave.typeOf());
// -> Dave is an employee
ES5ES5
ES6 Classes
class Person {
static type = 'person';
constructor(name) {
this.name = name;
}
typeOf() { return this.constructor.type; }
greet() { return `Hello, my name is ${this.name}`; }
}
class Employee extends Person {
static type = 'employee';
constructor(company, name) {
super(name);
this.company = company;
}
greet() {
return `${super.greet()}. I work at ${this.company}`;
}
}
ES6ES6
ES6 Classes
// create an instance
const Dave = new Employee('OCI', 'David');
// invoke methods
console.log(Dave.greet());
// -> Hello, my name is David. I work at OCI
// access static props via method
console.log(`Dave is an ${Dave.typeOf()}`);
// -> employee
ES6ES6
ModulesModules
import & export
named exports
default exports
importing defaults & named exports
Language-level support for modules for component
definition. Codifies patterns from popular JavaScript
module loaders (AMD, CommonJS). Runtime behaviour
defined by a host-defined default loader. Implicitly async
model – no code executes until requested modules are
available and processed.
Module Styles
// app.js
var math = require('lib/math');
math.sum(math.pi, math.pi);
Currently, the module loading spec is not defined completely and not
implemented in any engine. Node supports CommonJS; but other
async loading module formats exist like AMD and UMD.
// app.js
import math from 'lib/math';
math.sum(math.pi, math.pi)
ES5ES5 ES6ES6
// lib/math.js
exports.sum = sum;
function sum(x, y) {
return x + y;
}
var pi = exports.pi = 3.141593;
ES5ES5
// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
ES6ES6
Named & Default Exports
// Named exports
function sum(a,b) {
return a + b;
}
exports.sum = sum;
function div(a,b) {
return a / b;
}
exports.div = div;
// Module 'default' export
exports['default'] = function(n) {
return n * n;
}
module.exports = Object.assign(
exports['default'],
exports
);
Both CommonJS and ES6 allow for named exports and a
"default" export.
// Named exports
export sum = (a,b) => a + b;
export div = (a,b) => a / b;
// default export
export default (n) => n * n;
ES5ES5 ES6ES6
ES6 Modules
You can only have 1 default export per module. But you can
import the default or named exports in a number of ways.
// lib/math.js
// named exports
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
// default export
export default function(...nums) {
return Math.max(...nums);
}
ES6ES6
import max from 'lib/math';
max(1,2,3); // -> 3
import { square, diag } from 'lib/math';
square(2) // -> 4
diag(2,4) // -> 4.47213595499958
import max, { square, sqrt } from 'lib/math';
max(3,1,5); // -> 5
square(4); // -> 16
sqrt(9); // -> 3
ES6ES6

Idiomatic Javascript (ES5 to ES2015+)

  • 1.
  • 2.
    A Brief Historyof Time...A Brief History of Time...
  • 3.
    A Brief Historyof Time...A Brief History of Time... Official name of the language is ECMAScript ECMA is the Standardizations Body TC39 is the committee working on the standards. in 2015, ECMA decided to do yearly standards, hence the renaming.
  • 4.
    ES6 Browser SupportES6Browser Support Current browser support for ES6 is great on the desktop - not so much elsewhere http://kangax.github.io/compat-table/es6/ Current development uses ES6/next features through the use of transpilers like Babel
  • 5.
    Arrow FunctionsArrow Functions Arrowsare a function shorthand using the => syntax. They are syntactically similar to the related feature in C#, Java 8 and CoffeeScript. They support both expression and statement bodies. Unlike functions, arrows share the same lexical this as their surrounding code.
  • 6.
    Arrow Functions var list= [1,2,3,4,5]; list.map(function(n) { return n * 2; }, this); list.map(function(n) { return n * 2; }.bind(this)); In ES5, retaining the context of this in function expressions was typically done via Function#bind(); or through passing an execution context those few standard functions that allowed one. var list = [1,2,3,4,5]; list.map(n => n * 2); ES5ES5 ES6ES6
  • 7.
    Arrow Functions // Lexicalthis var brendan = { _name: 'Brendan Eich', _languages: ['assembly','javascript','C'], logLanguages: function() { this._languages.forEach(function (lang) { return console.log(this._name + ' knows ' + lang); }, this); } }; const brendan = { name: 'Brendan Eich', languages: ['assembly','javascript','C'], logLanguages: () => this.languages.forEach(lang => console.log(`${this.name} knows ${lang}`) ); }; ES5ES5 ES6ES6
  • 8.
    Block ScopingBlock Scoping Block-scopedbinding constructs. let is the new var.  const is single-assignment. Static restrictions prevent use before assignment.
  • 9.
    Block Scoping var a= 5; var b = 10; if (a === 5) { // IIFE !!! (function () { var a = 4; b = 1; console.log(a); // 4 console.log(b); // 1 })(); } console.log(a); // 5 console.log(b); // 1 ES5 required IIFEs in order to create pseudo-block scoping. ES6 gives us let, which is scoped to the enclosing block. var a = 5; var b = 10; if (a === 5) { let a = 4; // scope inside if-block var b = 1; // scope inside function console.log(a); // 4 console.log(b); // 1 } console.log(a); // 5 console.log(b); // 1 ES5ES5 ES6ES6
  • 10.
    Block Scoping // defineas a non-writable `constant` // and give it a value Object.defineProperties(window, { pi: { value: 3.14159265359, enumerable: true, writable: false } }); // var pi = 7; // Attempt to overwrite the constant pi = 15; console.log('Slice of pi: ' + pi); // 3.14159265359 const pi = 3.14159265359; // Attempt to overwrite the constant pi = 15; // TypeError: Assignment to constant console.log('Slice of pi: ' + pi); // 3.14159265359 // Never executes... ES5ES5 ES6ES6
  • 11.
    String TemplatesString Templates Templatestrings provide syntactic sugar for constructing strings. This is similar to string interpolation features in Perl, Python and more. Optionally, a tag can be added to allow the string construction to be customized, avoiding injection attacks or constructing higher level data structures from string contents.
  • 12.
    String Templates var name= 'Dan'; var dan = { projects: ['redux','react-dnd'] }; // concatenation console.log(name + ' Abramov'); //=> Dan Abramov // joining console.log( ['Known for ', dan.projects[0]].join('') ); //=> Known for redux ES5 had nothing similar. You would just concatenate strings with expressions.  ES6 allows interpolation of variables, expressions and functions inside template strings. ES5ES5
  • 13.
    String Templates const name= 'Dan'; const n = 10; const dan = { projects: ['redux','react-dnd'] }; const fn = () => 'reducers'; // variables console.log(`${name} Abramov`); // objects console.log(`Known for ${dan.projects[0]}`); // expression interpolation console.log(`${n} + 2 = ${n + 2}`); // functions console.log(`I love ${fn()}`); ES6ES6
  • 14.
    String Templates // Multilinestrings // 1. escaping - white space retained // 2. concatenation console.log( 'This string spans n multiple lines. It's crazy!n' + 'It's a bit harder to read' ); //=> This string spans //=> multiple lines. It's crazy! //=> It's a bit harder to read ES5ES5 // Multiline strings // - white space retained console.log( `This string spans multiple lines. It's crazy!` ); //=> This string spans //=> multiple lines. It's crazy! ES6ES6
  • 15.
    Object PropertiesObject Properties ObjectInitializer Shorthand Object Method Assignment Computed Properties Object literals are extended to support setting the prototype at construction, shorthand for foo: foo assignments, defining methods and making super calls. Together, these also bring object literals and class declarations closer together, and let object-based design benefit from some of the same conveniences.
  • 16.
    Object Properties function getPoint(){ var x = 1; var y = 10; return { x: x, y: y }; } getPoint(); //=> { x: 1, y: 10 } With property shorthand notation, if the property name and value variable are the same, no need to repeat yourself. function getPoint() { var x = 1; var y = 10; return { x, y }; } getPoint() //=> { x: 1, y: 10 } ES5ES5 ES6ES6
  • 17.
    Object Properties var object= { value: 42, toString: function toString() { return this.value; } }; object.toString() === 42; // -> true With object method assignment shorthand you can shorten method declarations on objects/classes as well. var object = { value: 42, toString() { return this.value; } }; console.log(object.toString() === 42); // -> true ES5ES5 ES6ES6
  • 18.
    Object Properties var prefix= 'foo'; var obj = {}; obj[prefix + 'bar'] = 'hello'; obj[prefix + 'baz'] = 'world'; console.log(obj['foobar']); // -> hello console.log(obj['foobaz']); // -> world With ES6 we now have the ability to use computed property names as well. You can evaluate any expression within [  ]. var foo = 'foo'; var fn = () => 'foo'; var obj = { [foo + 'bar']: 'hello', [fn() + 'baz']: 'world' }; console.log(obj['foobar']); // -> hello console.log(obj['foobaz']); // -> world ES5ES5 ES6ES6
  • 19.
    Destructuring AssignmentsDestructuring Assignments Destructuringallows binding using pattern matching, with support for matching arrays and objects. Destructuring is fail-soft, similar to standard object lookup foo["bar"], producing undefined values when not found.
  • 20.
    Destructuring var foo ={ bar: 'Kyle', baz: 'Simpson' }; var bar = foo[bar]; var baz = foo[baz]; // -> bar: 'Kyle', baz 'Simpson' var list = [1,2,3]; var one = list[0]; var two = list[1]; var three = list[2]; // -> one: 1, two: 2, three: 3 Binds the values from one Array or Object to another. const foo = { bar: 'Kyle', baz: 'Simpson' }; const {bar, baz} = foo; // -> bar: 'Kyle', baz 'Simpson' const list = [1,2,3]; const [one, two, three] = list; // -> one: 1, two: 2, three: 3 ES5ES5 ES6ES6
  • 21.
    Destructuring You can alsomap destructured objects to aliases as well. const foo = { bar: 'Kyle', baz: 'Simpson' }; const { bar: a, baz: b } = foo; // -> bar: 'Kyle', baz 'Simpson' ES6ES6
  • 22.
    Destructuring Or even pullout deeply nested properties  const person = { name: 'Steve', things: { one: 1, two: 2 }, years: [1975, 1995, 2015] }; const { name, things: { one }} = person; // -> name: Steve // -> one: 1 // But, if it's not there const stuff = { one: 1, two: 2 }; const { three } = stuff; // -> three: undefined ES6ES6
  • 23.
    Destructuring Plus, it makesit easier to do things like swapping variables without using an auxiliary. Or pulling out properties dynamically using computed property names. let a = 10, b = 20; [a, b] = [b, a]; // -> a = 20, b = 10 const key = 'doge'; const { [key]: foo } = { doge: 'such bar!' }; // -> foo = such bar! // Assign defaults (in case of undefined) const wow = { such: 'awesome' }; const { much='missing' } = wow; // -> much = missing // Skip over elements in arrays let [,,c,d] = [1,2,3,4,5]; // -> c = 3 // -> d = 4 ES6ES6
  • 24.
    Function ArgumentsFunction Arguments DefaultArguments Spread Rest Callee-evaluated default parameter values. Turn an array into consecutive arguments in a function call. Bind trailing parameters to an array. Rest replaces the need for arguments and addresses common cases more directly.
  • 25.
    Default Argument Values functioniam(name) { (name === undefined) && (name="Batman"); console.log("I am " + name + '!'); } iam(); // -> I am Batman! Similar to the default assignments used in destructuring, functions allow you assign default values as well. If the parameter passed is undefined, it gets the default. function iam(name="batman") { console.log(`I am ${name}!`); } iam(); // -> I am Batman! ES5ES5 ES6ES6
  • 26.
    Defaults & Destructuring Youcan even use destructuring and defaults on function arguments  function random ({ min=1, max=300 }) { return Math.floor(Math.random() * (max - min)) + min; } random({}); // -> 174 random({max: 24}); // -> 18 // Or, make the whole argument optional function random ({ min=1, max=300 }={}) { return Math.floor(Math.random() * (max - min)) + min; } random(); // -> 133 ES6ES6
  • 27.
    The spread operatorpulls individual items out of a collection (Array or Object). function reducer(state={}, action) { switch(action.type) { case 'SET_AGE': return { ...state, age: action.age }; default: return state; } } const state = { name: 'Dave', age: 40 }; const action = { type: 'SET_AGE', age: 41 }; reducer(state, action); // -> { name: 'Dave', age: 41 } ES6ES6 ... spread operator
  • 28.
    var nums =[4,1,9,5]; Math.max.apply(null, nums); // -> 9 let a = [1,2,3]; let b = [4,5,6]; // join var c = a.concat(b); // -> c = [1,2,3,4,5,6] // copy var d = [].slice.call(c, 0); // -> d = [1,2,3,4,5,6] // splice var e = [0,7,8]; var f = e.slice(0,1) .concat(c, e.slice(1), [9,10]); // -> f = [0,1,2,3,4,5,6,7,8,9,10] Works with Arrays as well (non-mutating). let nums = [4,1,9,5]; Math.max(...nums); // -> 9 let a = [1,2,3]; let b = [4,5,6]; // join let c = [...a, ...b]; // -> c = [1,2,3,4,5,6] // copy let d = [...c]; // -> d = [1,2,3,4,5,6] // splice let e = [0, ...d, 7, 8, ...[9,10]]; // -> e = [0,1,2,3,4,5,6,7,8,9,10] ES5ES5 ES6ES6 ... spread operator
  • 29.
    function join(sep /*,...args*/) { var args = [].slice.call(arguments, 1); return args.join(sep); } join(', ', 'john', 'bobby', 'ted') // -> 'john, bobby, ted' The rest operator (or, gather) allows us to pull values into a collection Array or Object. const join = (sep, ...args) => args.join(sep); join(':', "one", "two", "three"); // -> one:two:three ES5ES5 ES6ES6 ... rest operator
  • 30.
    You can evenuse it with destructuring to gather values. var list = [1,2,3,4,5]; var [head, ...tail] = list; // -> head = 1 // -> tail = [2,3,4,5] var list = [1,2,3,4,5]; var [head, ...tail] = list; console.log(head, tail); var passed = { className: 'panel', style: { color: '#369'}, title: 'Panel', active: true }; var { className, style, ...props } = passed; // -> className = 'panel' // -> styles = { color: '#369' } // -> props = { title: 'Panel', active: true } ES6ES6 ... rest operator
  • 31.
    Iterators & ArraysIterators& Arrays Iterators allow us to traverse a collection. Generalize for..in to custom iterator-based iteration with for..of. Array#from allows us to convert array-like collections into real arrays.
  • 32.
    Iterators & Arrays vara = [1,2,3]; a.forEach(function (element) { console.log(element); }); // -> 1 2 3 // Using a for loop var a = [1,2,3]; for (var i = 0; i < a.length; ++i) { console.log(a[i]); } // -> 1 2 3 // Uses an iterator behind the scenes for (let element of [1, 2, 3]) { console.log(element); } // => 1 2 3 ES5ES5 ES6ES6
  • 33.
    Iterators function iteratorFor(list) { vari = 0; return { next: function() { return { value: list[i++], done: i > list.length }; } } } var iter = iteratorFor([1,2,3]); var res = iter.next(); while (!res.done) { console.log(res); res = iter.next(); } // -> Same output as right-side What is an iterator?  ES6 let's us access them via predefined Symbol properties.  let iter = [1, 2, 3][Symbol.iterator](); console.log(iter.next()); // -> {value: 1, done: false} console.log(iter.next()); // -> {value: 2, done: false} console.log(iter.next()); // -> {value: 3, done: false} console.log(iter.next()); // -> {value: undefined, done: true} ES5ES5 ES6ES6
  • 34.
    Iterators with Generators Youcan write your own iterators using ES6 generator functions and yield.  function* iteratorFor(list) { for (let item of list) { yield item; } } const iter = iteratorFor([1,2,3]); for (let value of iter) { console.log(value); } // -> 1 2 3 // can't use iter again let iter2 = iteratorFor([1,2,3]); console.log([...iter2]); // -> [1,2,3] ES6ES6
  • 35.
    ClassesClasses ES2015 classes area simple sugar over the prototype-based OO pattern. Having a single, convenient, declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.
  • 36.
    // Person "Class" functionPerson(name) { this.name = name; } Person.type = 'person'; Person.prototype.greet = function() { return 'Hello, my name is ' + this.name + '.'; } Person.prototype.typeOf = function() { return this.constructor.type; } // Employee "Class" function Employee(company, name) { Person.call(this, name); this.company = company; } Employee.type = 'employee'; // setup inheritance via prototype chain Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Employee; // Override greet method Employee.prototype.greet = function() { return Person.prototype.greet.call(this) + ' I work at ' + this.company } ES5ES5
  • 37.
    ES5 "Classes" // createan instance var Dave = new Employee('OCI', 'David'); // call a method Dave.greet(); // -> Hello, my name is David. I work at OCI // access "static" property via method console.log('Dave is an ' + Dave.typeOf()); // -> Dave is an employee ES5ES5
  • 38.
    ES6 Classes class Person{ static type = 'person'; constructor(name) { this.name = name; } typeOf() { return this.constructor.type; } greet() { return `Hello, my name is ${this.name}`; } } class Employee extends Person { static type = 'employee'; constructor(company, name) { super(name); this.company = company; } greet() { return `${super.greet()}. I work at ${this.company}`; } } ES6ES6
  • 39.
    ES6 Classes // createan instance const Dave = new Employee('OCI', 'David'); // invoke methods console.log(Dave.greet()); // -> Hello, my name is David. I work at OCI // access static props via method console.log(`Dave is an ${Dave.typeOf()}`); // -> employee ES6ES6
  • 40.
    ModulesModules import & export namedexports default exports importing defaults & named exports Language-level support for modules for component definition. Codifies patterns from popular JavaScript module loaders (AMD, CommonJS). Runtime behaviour defined by a host-defined default loader. Implicitly async model – no code executes until requested modules are available and processed.
  • 41.
    Module Styles // app.js varmath = require('lib/math'); math.sum(math.pi, math.pi); Currently, the module loading spec is not defined completely and not implemented in any engine. Node supports CommonJS; but other async loading module formats exist like AMD and UMD. // app.js import math from 'lib/math'; math.sum(math.pi, math.pi) ES5ES5 ES6ES6 // lib/math.js exports.sum = sum; function sum(x, y) { return x + y; } var pi = exports.pi = 3.141593; ES5ES5 // lib/math.js export function sum(x, y) { return x + y; } export var pi = 3.141593; ES6ES6
  • 42.
    Named & DefaultExports // Named exports function sum(a,b) { return a + b; } exports.sum = sum; function div(a,b) { return a / b; } exports.div = div; // Module 'default' export exports['default'] = function(n) { return n * n; } module.exports = Object.assign( exports['default'], exports ); Both CommonJS and ES6 allow for named exports and a "default" export. // Named exports export sum = (a,b) => a + b; export div = (a,b) => a / b; // default export export default (n) => n * n; ES5ES5 ES6ES6
  • 43.
    ES6 Modules You canonly have 1 default export per module. But you can import the default or named exports in a number of ways. // lib/math.js // named exports export const sqrt = Math.sqrt; export function square(x) { return x * x; } export function diag(x, y) { return sqrt(square(x) + square(y)); } // default export export default function(...nums) { return Math.max(...nums); } ES6ES6 import max from 'lib/math'; max(1,2,3); // -> 3 import { square, diag } from 'lib/math'; square(2) // -> 4 diag(2,4) // -> 4.47213595499958 import max, { square, sqrt } from 'lib/math'; max(3,1,5); // -> 5 square(4); // -> 16 sqrt(9); // -> 3 ES6ES6