1 of 291

ES6 IN PRACTICE

TIM DOHERTY

2 of 291

Who am I?

3 of 291

4 of 291

5 of 291

6 of 291

7 of 291

8 of 291

9 of 291

10 of 291

Before we get started...

11 of 291

A brief history...

12 of 291

13 of 291

14 of 291

But the marketing gods had to be appeased…

15 of 291

…and recruiters weren’t confused enough

16 of 291

Script

17 of 291

and they saw that it was good

18 of 291

so they standardized it…

19 of 291

…but what to call this new language?

20 of 291

WebScript?

21 of 291

WebScript?

BrowserScript?

22 of 291

WebScript?

BrowserScript?

SchemeScript?

23 of 291

24 of 291

25 of 291

WebScript?

BrowserScript?

SchemeScript?

EczemaScript?

26 of 291

WebScript?

BrowserScript?

SchemeScript?

ECzeMAScript?

27 of 291

WebScript?

BrowserScript?

SchemeScript?

ECMAScript

28 of 291

ECMAScript 1

29 of 291

ECMAScript 1

ECMAScript 2

30 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

31 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

32 of 291

33 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

34 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

ECMAScript 3.1

35 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

ECMAScript 3.1

36 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

ECMAScript 3.1

ECMAScript 5

37 of 291

ECMAScript 1

ECMAScript 2

ECMAScript 3

ECMAScript 4

ECMAScript 3.1

ECMAScript 5

ECMAScript 2015

38 of 291

Umm… 6?

39 of 291

ECMA-262 6th Edition, ECMAScript 2015

40 of 291

“ES6 is a radical jump forward for the language”

~ Kyle Simpson

“…geared toward solving problems that developers actually face.”

~ Nicholas Zakas

“…adds significant new syntax for writing complex applications”

~ Wikipedia

“ES6 is a large and important update to JavaScript”

~ Wes Bos

“ECMAScript 6 will introduce many great features”

~ Dr. Axel Rauschmayer

“ES6 is a significant update to the language”

~ Luke Hoban

“Now this dream is coming true, not just in ES6 draft specs...”

~ Brendan Eich

41 of 291

“ES6 is a radical jump forward for the language”

~ Kyle Simpson

“…geared toward solving problems that developers actually face.”

~ Nicholas Zakas

“…adds significant new syntax for writing complex applications”

~ Wikipedia

“ES6 is a large and important update to JavaScript”

~ Wes Bos

“ECMAScript 6 will introduce many great features”

~ Dr. Axel Rauschmayer

“ES6 is a significant update to the language”

~ Luke Hoban

“Now this dream is coming true, not just in ES6 draft specs...”

~ Brendan Eich

On Over 100 Ten-Best Lists!

42 of 291

43 of 291

44 of 291

45 of 291

46 of 291

47 of 291

48 of 291

ES6 in Depth

49 of 291

50 of 291

51 of 291

52 of 291

53 of 291

54 of 291

55 of 291

JavaScript Sucks!

56 of 291

57 of 291

“Can’t we just wait for browsers to catch up?”

58 of 291

59 of 291

It’s not 2009 anymore

60 of 291

61 of 291

62 of 291

F

U

D

EAR

NCERTAINTY

OUBT

63 of 291

64 of 291

65 of 291

66 of 291

67 of 291

Now What?

68 of 291

69 of 291

70 of 291

71 of 291

$ npm install --save-dev ui-build

72 of 291

73 of 291

74 of 291

75 of 291

76 of 291

77 of 291

78 of 291

79 of 291

80 of 291

81 of 291

82 of 291

83 of 291

ES6 in Depth

(abridged)

84 of 291

85 of 291

86 of 291

87 of 291

What’s the big deal?

88 of 291

JavaScript

89 of 291

Despite its quirks

90 of 291

JavaScript is the most widely deployed

programming language

91 of 291

92 of 291

93 of 291

Any application that can be written in JavaScript, �will eventually be written in JavaScript.�~Atwood's Law

94 of 291

95 of 291

Syntax

noun | syn·tax | \ˈsin-ˌtaks\

  1. a : the way in which linguistic elements (such as words) are put together to form constituents (such as phrases or clauses)

b : the part of grammar dealing with this�

  1. : a connected or orderly system : harmonious arrangement of parts or elements the syntax of classical architecture�
  2. : syntactics especially as dealing with the formal properties of languages or calculi

96 of 291

97 of 291

98 of 291

99 of 291

100 of 291

101 of 291

102 of 291

Enhancement

noun | en·hance·ment | \enˈhansmənt\

  1. : an increase or improvement in quality, value, or extent. "these enhancements will improve the customer experience"

103 of 291

104 of 291

105 of 291

106 of 291

Feature

noun | fea·ture | \ˈfē-chər\

  • : a special attraction: such as�a : a featured motion picture�b : a featured article, story, or department in a newspaper or magazine An account of the fire was the feature in the Sunday newspaper.�c : something offered to the public or advertised as particularly attractive one of the car's most popular features

107 of 291

108 of 291

109 of 291

110 of 291

111 of 291

112 of 291

.updates {text-decoration: underline !important;}

113 of 291

Syntax

114 of 291

let foo = 'bar', bar = 'baz';let obj = {� foo,� bar() {return this[bar];},[bar]: 'bim'};�obj.foo; // bar�obj.baz; // bim�obj.bar(); // bim

115 of 291

function greet(first='John', last='Doe') {return `Hello ${first} ${last}`;}��greet(); // Hello John Doe�greet('Jane'); // Hello Jane Doe�greet('Fred', 'Smith'); //Hello Fred Smith

116 of 291

JavaScript

117 of 291

...

118 of 291

119 of 291

120 of 291

// ES5function func() {var args = [].slice.call(arguments);� args.map().reduce().filter().etc();}��// ES6 restfunction func(...args) {� args.map().reduce().filter().etc();}

121 of 291

function doTheThing(arg1, arg2, arg3, doIt = true) {// do the thing}��function dontDoTheThing(...args) {� args.push(false)� doTheThing.apply(undefined, args);}��dontDoTheThing(a, b, c);

// doTheThing(a, b, c, false);

122 of 291

123 of 291

var a1 = [1, 4];var a2 = [2, 3];��// ES5�a1.splice(1, 0, a2); // [1, 2, 3, 4] ��// ES6var a3 = [1, ...a2, 4]; // [1, 2, 3, 4]

124 of 291

function doTheThing(arg1, arg2, arg3, doIt = true) {// do the thing}��function dontDoTheThing(...args) {� doTheThing(...args, false);}��dontDoTheThing(a, b, c);

// doTheThing(a, b, c, false);

125 of 291

126 of 291

let { a: { b: { c: { d: { e } } } } } = { � a: { � b: { � c: { � d: { � e: 'foo'}}}}};�console.log(e); // foo

127 of 291

import { React, Component } from 'react';

128 of 291

import React from 'react';��function MyComponent({ foo, bar, baz }) {return (<div>{foo} {bar} {baz}</div>);}

129 of 291

function fn({foo='bar', bar='baz'} = {}) {return `foo: ${foo}, bar: ${bar}`;}��fn(); // foo: bar, bar: baz�fn({foo: 'fooey'}); // foo: fooey, bar: baz

130 of 291

131 of 291

var foo = 'bar';��{// this is a valid block in ES5var foo = 'baz';}��console.log(foo); // 'baz'

132 of 291

let foo = 'bar';��{let foo = 'baz';� console.log(foo); // 'baz'}��console.log(foo); // 'bar'

133 of 291

function iterate() {var i = 0, funcs = [];for (;i < 5; i++) {� funcs.push(function () {alert(i);});}return funcs;}

(iterate()).forEach(function (element) {� element(); // 5}

134 of 291

function iterate() {var i =0, funcs = [];for (;i < 5; i++) {(function (j) {� funcs.push(function () {alert(j);});})(i);}return funcs;}

135 of 291

function iterate() {var funcs = [];for (let i = 0;i < 5; i++) {� funcs.push(function () {alert(i);});}return funcs;}

136 of 291

const

137 of 291

const obj = { foo: 'bar' };

obj.bar = 'baz';

console.log(obj);

// Object { foo: 'bar', bar: 'baz' };

138 of 291

139 of 291

const !== immutable

140 of 291

()=>{}

141 of 291

arg => expr��arg => { stmt1; stmt2; ... }��arg => ({})��(arg1, arg2, ...) => expr��(arg1, arg2, ...) => { stmt1; stmt2; ... }��(arg1, arg2, ...) => ({})

142 of 291

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1].map(n => n * 3).filter(n => n % 2 === 0).sort((a, b) => a - b).reduce((prev, curr) => prev + curr, 0);

fetch('http://domain.com').then(response => response.json()).then(data => data).catch(err => err.message);

143 of 291

const obj = {� foo: 'bar',� method() {setTimeout(() => {� console.log(this.foo);}, 0);}};��obj.method(); // bar

144 of 291

const multiplier = n => a => a * n;��const double = multiplier(2);const triple = multiplier(3);��double(3); // 6�triple(3); // 9

145 of 291

146 of 291

console.log(foo()); // bar�console.log(bar()); // TypeError

function foo() { return 'bar'; }��var bar = () => 'baz';

147 of 291

const obj = {� foo: 'bar'};��const method = (() => {� console.log(this.foo);}).bind(obj);��method(); // undefined

148 of 291

Template Literals

149 of 291

// ES5var url = 'http://' + [host, path, id].join('/');��// ES6let url = `http://${host}/${path}/${id}`;

150 of 291

// ES5 with Underscore/Lodash

var tpl = _.template('hello <%= name %>!');var output = tpl({ name: 'fred' });��// ES6let user = { name: 'fred' };let output = `hello ${user.name}`;

151 of 291

let view = {� state: { name: 'World' },� render() {return `� <div>� Hello ${this.state.name}!</div>� `;}};�document.body.innerHTML = view.render();

152 of 291

error quotes Strings must use singlequote

153 of 291

154 of 291

Namespacing

IIFE

JavaScript Module Pattern

CommonJS

AMD

155 of 291

156 of 291

157 of 291

// module1.jsexport function one() {}export function two() {}export default { one, two };��// module2.jsimport module1 from './module1';import { one, two as three } from 'module1';import * as oneTwo from 'module1';

158 of 291

159 of 291

160 of 291

161 of 291

162 of 291

163 of 291

164 of 291

HTTP

HTTP

+

165 of 291

166 of 291

167 of 291

Enhancements

168 of 291

169 of 291

let str = 'Hello world!';��// ES5�str.indexOf('Hello') !== -1 // true�str.indexOf('foobar') !== -1 // false��// ES6�str.includes('Hello') // true�str.includes('foobar') // false

170 of 291

let str = 'Hello world!';��// ES5�str.indexOf('Hello') === 0 // true��// ES6�str.startsWith('Hello') // true

171 of 291

let str = 'Hello world!';��// ES5�str.substr(� str.length - 'world!'.length - 1) === 'world!' // true��// ES6�str.endsWith('world!') // true

172 of 291

173 of 291

Array.from('abc'); // ['a', 'b', 'c']�Array.of('abc'); // ['abc']

let a = [1, 2, 3, 4, 5];�a.find(e => e % 3 === 0); // 3�a.findIndex(e => e % 3 === 0); // 2

[1, 2, 3].fill(4); // [4, 4, 4][1, 2, 3].copyWithin(0, 2); // [3, 2, 3]

174 of 291

175 of 291

Number.EPSILON�Number.MAX_SAFE_INTEGER�Number.MIN_SAFE_INTEGER�Number.isNaN()�Number.isFinite()�Number.isInteger()�Number.isSafeInteger()�Number.parseInt()�Number.parseFloat()

176 of 291

177 of 291

Math.acosh()�Math.asinh()�Math.atanh()�Math.cosh()�Math.sinh()�Math.tanh()�Math.cbrt()�Math.clz32()�Math.expm1()�Math.fround()�

Math.hypot()�Math.imul()�Math.log10()�Math.log1p()�Math.log2()�Math.sign()�Math.trunc()

178 of 291

179 of 291

180 of 291

let obj1 = { foo: 'bar' };let obj2 = { bar: 'baz' };

let obj3 = Object.assign({}, obj1, obj2);��Obj3; // { foo: 'bar', bar: 'baz' }

181 of 291

182 of 291

let obj1 = { � foo: 'bar', � baz: [1, 2, 3]};let obj2 = Object.assign({}, obj1);��obj2.baz.push(4);�console.log(obj1.baz); // [1, 2, 3, 4]

183 of 291

let obj1 = Object.create({ bar: 'baz' });��obj1.foo = 'bar';��let o1Proto = Object.getPrototypeOf(obj1);let obj2 = Object.assign(� Object.create(o1Proto),� obj1�);��obj2.bar // 'baz'

184 of 291

185 of 291

186 of 291

let sym = Symbol();let o = {[sym]: 'foo',� bar: 'baz'};��o[sym]; // 'foo'�Object.getOwnPropertyNames(o); // ['bar']�Object.getOwnPropertySymbols(o); // [Symbol()]

187 of 291

let Thing = (function () {let nameSymbol = Symbol();return class Thing {� constructor(name) {this[nameSymbol] = name;}� get name() {return this[nameSymbol];}};})();

188 of 291

189 of 291

Iteratables

190 of 291

interface Iterable {[Symbol.iterator]() : Iterator;}��interface Iterator {� next() : IteratorResult;return?(value? : any) : IteratorResult;}��interface IteratorResult {� value : any;� done : boolean;}

191 of 291

let arr = [1, 2, 3, 4];let iterator = arr[Symbol.iterator]();let result = iterator.next();��while(!result.done) {� console.log(result.value);� result = iterator.next();}

192 of 291

let arr = [1, 2, 3, 4];��for (let i of arr) {� console.log(i);}

193 of 291

[...'Hello'[Symbol.iterator]()];

// ['H', 'e', 'l', 'l', 'o']

194 of 291

const myObject = {[Symbol.iterator]() {return {� next() {

// your implementation here

}

};

}};

195 of 291

196 of 291

197 of 291

198 of 291

199 of 291

200 of 291

201 of 291

202 of 291

function* countDown(count) {while (count--) {yield count;}}��[...countDown(5)]��//[4, 3, 2, 1, 0]

203 of 291

204 of 291

function* even(iterable) {for (let n of iterable) {if (n % 2 === 0) { yield n; }}}��function* take(n, iterable) {const iter = iterable[Symbol.iterator]();while(n--) { yield iter.next().value; }}��let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];[...take(3, even(arr))]; // [2, 4, 6]

205 of 291

206 of 291

function consume(iterable, consumer) {� consumer.next();for (let x of iterable) { consumer.next(x); }� consumer.return();}��function* processAndLog() {while (true) {const val = yield;� process(val);� logToServer(`Processed ${val} at ${new Date()}`);}}��consume([1, 2, 3, 4], processAndLog());

207 of 291

208 of 291

import { call, put } from 'redux-saga/effects'� �import myApi from '_shared/myApi';import { actions } from '../module';� �export function* getItems({ payload }) {try {const response = yield call(myApi.get, payload);yield put(actions.setData(response.data));} catch (err) {yield put(actions.handleFailure(err));}

}

209 of 291

210 of 291

211 of 291

212 of 291

var obj = { foo: 'bar', baz: 'bim' };��Object.keys(foo);// ['foo', 'baz']��obj.hasOwnProperty('foo'); // true

213 of 291

214 of 291

var obj = { foo: 'bar', baz: 'bim' };��Object.defineProperty(obj, 'fee', {� value: 'fum',� writable: true,� enumerable: true});

215 of 291

216 of 291

217 of 291

?

218 of 291

// ES5var obj = { foo: 'bar', baz: 'bim' }, proxy;��Object.keys(obj).forEach(function(key) {� Object.defineProperty(proxy, key, {� get: function () {/*trap here...*/},

set: function (val) {/*trap here...*/}});});

219 of 291

let person = new Proxy({}, {� set(target, prop, value) {if (prop === 'age') {if (!Number.isInteger(value)) {throw new TypeError('Age must be a number');}}� target[prop] = value;return true;}});��person.age = 47;�console.log(person.age); // 47�person.age = 'foo'; // TypeError

220 of 291

const storage = new Proxy({}, {� get(target, prop, receiver) {

return localStorage.getItem(prop);

},� set(target, prop, value) {

localStorage.setItem(prop, value);

}});��storage.foo = { bar: 'baz' };�console.log(storage.foo); // { bar: 'baz' };

221 of 291

let sum = (a, b) => a + b;

let multiplier = (multiple) => ({� apply (target, ctx, args) {return Reflect.apply(...args) * multiple� }});��let sumTwice = new Proxy(sum, multiplier(2));let sumThrice = new Proxy(sum, multiplier(3));�console.log(sumTwice(1, 2)); // 6�console.log(sumThrice(1, 2)); // 9

222 of 291

Reflect.apply()

Reflect.construct()

Reflect.defineProperty()

Reflect.deleteProperty()

Reflect.enumerate()

Reflect.get()

Reflect.getOwnPropertyDescriptor()

Reflect.getPrototypeOf()

Reflect.has()

Reflect.isExtensible()

Reflect.ownKeys()

Reflect.preventExtensions()

Reflect.set()

Reflect.setPrototypeOf()

223 of 291

224 of 291

let obj = { foo: 'bar', _baz: 'bim' };��let {proxy, revoke} = Proxy.revocable(obj, {� set(target, key, value) {if (key[0] === '_') {� revoke();}}});��proxy.foo = 'fum'; // ok�proxy._baz = 'bar'; // proxy revoked�console.log(proxy._baz); // TypeError

225 of 291

226 of 291

Finally!

227 of 291

Finally!

228 of 291

const p = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'kept');});��p.then(/* resolved */)

.catch(/* rejected or error */);��Promise.resolve();�Promise.reject();�Promise.all();�Promise.race();

229 of 291

230 of 291

231 of 291

232 of 291

233 of 291

document.querySelector();

234 of 291

new Promise((resolve, reject) => { ... });

235 of 291

236 of 291

237 of 291

Syntax

noun | syn·tax | \ˈsin-ˌtaks\

  • a : the way in which linguistic elements (such as words) are put together to form constituents (such as phrases or clauses)

b : the part of grammar dealing with this�

  • : a connected or orderly system : harmonious arrangement of parts or elements the syntax of classical architecture�
  • : syntactics especially as dealing with the formal properties of languages or calculi

238 of 291

Who cares?

239 of 291

240 of 291

241 of 291

=

242 of 291

243 of 291

ES6 > ES5 > UglifyJS > Webpack > ?

244 of 291

245 of 291

246 of 291

JavaScript still doesn’t have classes

247 of 291

248 of 291

249 of 291

class Foo {� constructor(baz) {this.bar = baz;}� foobar() {return this.bar;}}

250 of 291

function Foo(baz) {this.bar = baz;}

�Foo.prototype.foobar = function() {return this.bar;};

251 of 291

class Bar {

// ...

}

class Foo extends Bar {

// ...

}

252 of 291

function Bar() {

// ...

}

function Foo() {

// ...

}

�Foo.prototype = new Bar();

253 of 291

254 of 291

255 of 291

256 of 291

257 of 291

  • Terser syntax
  • Static analysis
  • Tooling
  • Community was doing it anyway
  • Friendlier to classical OO devs

258 of 291

259 of 291

  • Syntax vs. semantics
  • Encourages inheritance hierarchies
  • JavaScript still doesn’t have classes
  • Confusing to classical OO devs

260 of 291

“Sometimes when I'm writing Javascript I want to throw up my hands and say "this is bullshit!" but I can never remember what "this" refers to”

Ben Halpern @bendhalpern

261 of 291

import { Component } from '@angular/core';��@Component({� selector: 'my-app',� template: `<h1>Hello {{name}}</h1>`�})export class AppComponent { name = 'Angular'; }

262 of 291

class Welcome extends React.Component {� constructor(props) {super(props);this.state = { greeting: 'Hello' };}� render: () => (<h1>this.state.greeting, {this.props.name}</h1>)}

263 of 291

264 of 291

265 of 291

Go Native!

266 of 291

$.extend();�_.extend();�angular.extend();��// ES6�Object.assign();

267 of 291

_.find();��// ES6�Array.prototype.find();

268 of 291

_.startsWith();�_.endsWith();�_.includes();*��// ES6�String.prototype.startsWith();�String.prototype.endsWith();�String.prototype.includes();

269 of 291

var tpl = _.template('hello <%= name %>!');var output = tpl({ name: 'fred' });��// ES6let user = { name: 'fred' };let output = `hello ${user.name}`;

270 of 291

var jqPromise = (jQuery.Deferred()).promise();var qPromise = (Q.defer()).promise;var ngPromise = ($q.defer()).promise;

var bbPromise = new Bluebird.promise(

function (resolve, reject) {}

);��// ES6let p = new Promise((resolve, reject) => {});

271 of 291

272 of 291

273 of 291

274 of 291

275 of 291

276 of 291

277 of 291

What’s next?

278 of 291

279 of 291

280 of 291

281 of 291

ES 2016

282 of 291

ES 2016

  • Array.prototype.includes
  • Exponentation operator

283 of 291

284 of 291

ES 2017

285 of 291

286 of 291

287 of 291

ES 2017

  • Async functions
  • Shared memory and atomics
  • Object.values / Object.entries
  • Object.getOwnPropertyDescriptors
  • String padding
  • Trailing commas in function params / calls

288 of 291

ES 2018

ES 2019

ES 2020

...and beyond

289 of 291

290 of 291

291 of 291

THANKS!

@TimCDoherty