Slide 1

Slide 1 text

TC39, ECMAScript, and the Future of JavaScript

Slide 2

Slide 2 text

ponyfoo.com twitter.com/nzgb

Slide 3

Slide 3 text

ponyfoo.com/books

Slide 4

Slide 4 text

What’s TC39?

Slide 5

Slide 5 text

isNaN(NaN) // true isNaN(“A”) // true “A” == NaN // false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true

Slide 6

Slide 6 text

isNaN(NaN) // true isNaN(“A”) // true “A” == NaN // false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true

Slide 7

Slide 7 text

isNaN(NaN) // true isNaN(“A”) // true “A” == NaN // false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true

Slide 8

Slide 8 text

isNaN(NaN) // true isNaN(“A”) // true “A” == NaN // false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true

Slide 9

Slide 9 text

+0 == -0 // true +0 === -0 // true 1/+0 === 1/-0 // false

Slide 10

Slide 10 text

Write valid JavaScript with only +!()[] jsfuck.com

Slide 11

Slide 11 text

Specification Development Process

Slide 12

Slide 12 text

Living Standard tc39.github.io/ecma262 github.com/tc39/proposals

Slide 13

Slide 13 text

Stage 0

Slide 14

Slide 14 text

Stage 1

Slide 15

Slide 15 text

Stage 2

Slide 16

Slide 16 text

Stage 3

Slide 17

Slide 17 text

Stage 4

Slide 18

Slide 18 text

prop-tc39.now.sh

Slide 19

Slide 19 text

Release Cadence

Slide 20

Slide 20 text

Proposals

Slide 21

Slide 21 text

Array#includes (Stage 4) [1,2].indexOf(2) !== -1 // true [1,2].indexOf(3) !== -1 // false [1,2].includes(2) // true [1,2].includes(3) // false

Slide 22

Slide 22 text

Array#includes (Stage 4) [1,2].indexOf(2) !== -1 // true [1,2].indexOf(3) !== -1 // false [1,2].includes(2) // true [1,2].includes(3) // false

Slide 23

Slide 23 text

Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 24

Slide 24 text

Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 25

Slide 25 text

Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 26

Slide 26 text

Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 27

Slide 27 text

Async Functions (Stage 4) await fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 28

Slide 28 text

Async Functions (Stage 4) const res = await fetch(‘/api/products’) .then(res => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 29

Slide 29 text

Async Functions (Stage 4) const res = await fetch(‘/api/products’) const data = await res.json() .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })

Slide 30

Slide 30 text

Async Functions (Stage 4) const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) .catch(err => { console.log(‘Update failed’, err) })

Slide 31

Slide 31 text

Async Functions (Stage 4) try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) }

Slide 32

Slide 32 text

Async Functions (Stage 4) async function main() { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } }

Slide 33

Slide 33 text

Async Functions (Stage 4) (async () => { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })()

Slide 34

Slide 34 text

Async Functions (Stage 4) (async () => { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() await (2 + 3)

Slide 35

Slide 35 text

Async Functions (Stage 4) (async () => { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() `Price: ${ await getPrice() }`

Slide 36

Slide 36 text

Async Functions (Stage 4) (async () => { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() renderView(await getPrice())

Slide 37

Slide 37 text

Async Functions (Stage 4) (async () => { try { const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() 2 * (await getPrice())

Slide 38

Slide 38 text

Async Functions (Stage 4) const sleep = delay => new Promise(resolve => setTimeout(resolve, delay) ) const slowLog = async (...terms) => { await sleep(2000) console.log(...terms) } slowLog(‘Well that was underwhelming’) .then(() => console.log(‘Nailed it!’)) .catch(reason => console.error(‘Failed’, reason))

Slide 39

Slide 39 text

Async Iteration (Stage 3) const list = { [Symbol.iterator]() { let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }

Slide 40

Slide 40 text

Async Iteration (Stage 3) const list = { [Symbol.iterator]() { let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }

Slide 41

Slide 41 text

Async Iteration (Stage 3) const list = { [Symbol.iterator]() { let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }

Slide 42

Slide 42 text

Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() { let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } }

Slide 43

Slide 43 text

Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() { let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } } for await (const i of items) { // <- 0, 1, 2, 3, 4 }

Slide 44

Slide 44 text

Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() { let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } } async function readItems() { for await (const i of items) { // <- 0, 1, 2, 3, 4 } }

Slide 45

Slide 45 text

Async Iteration (Stage 3) async function* getProducts(categoryUrl) { const listReq = await fetch(categoryUrl) const list = await listReq.json() for (const product of list) { const productReq = await product.url const product = await productReq.json() yield product } }

Slide 46

Slide 46 text

Async Iteration (Stage 3) async function* getProducts(categoryUrl) { const listReq = await fetch(categoryUrl) const list = await listReq.json() for (const product of list) { const productReq = await product.url const product = await productReq.json() yield product } } async function readProducts() { const g = getProducts(category) for await (const product of g) { // use product details } }

Slide 47

Slide 47 text

Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" }, { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}

Slide 48

Slide 48 text

Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" }, { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}

Slide 49

Slide 49 text

Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" }, { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}

Slide 50

Slide 50 text

Rest/Spread Properties (Stage 3) const item = { id: '4fe09c27', name: 'Banana', amount: 3 } const { id, ...rest } = item // <- { name: 'Banana', amount: 3 }

Slide 51

Slide 51 text

Rest/Spread Properties (Stage 3) function print({ id, ...rest }) { console.log(rest) } print({ id: '4fe09c27', name: 'Banana' }) // <- { name: 'Banana'}

Slide 52

Slide 52 text

Dynamic import() (Stage 3) import markdown from './markdown' // ... export default compile

Slide 53

Slide 53 text

Dynamic import() (Stage 3) import(`./i18n.${ navigator.language }.js`) .then(module => console.log(module.messages)) .catch(reason => console.error(reason))

Slide 54

Slide 54 text

Named Captures (Stage 3) const urlRegExp = /^(?: (http[s]?|ftp):\/)?\/?([^:\/ \s]+)((?:\/\w+)*\/)([\w\-\.]+ [^#?\s]+)([^#]*)?(#[\w\-]+)?$/

Slide 55

Slide 55 text

Named Captures (Stage 3) const urlRegExp = /^(?:(? http[s]?|ftp):\/)? \/?(?[^:\/\s]+)(? (?:\/\w+)*\/)(? [\w\-\.]+[^#?\s]+)(? [^#]*)?(?#[\w\-] +)?$/u

Slide 56

Slide 56 text

Named Captures (Stage 3) const urlRegExp = /^(?(? http[s]?|ftp):\/)? \/?(?[^:\/\s]+)(? (?:\/\w+)*\/)(? [\w\-\.]+[^#?\s]+)(? .*)?(?#[\w\-]+)? $/ const url = 'https://commits.com/8b48e3/diff?w=1#readme' const { groups } = urlRegExp.exec(url) console.log(groups) { protocol: 'https', host: 'commits.com', path: '/8b48e3/', file: 'diff', query: '?w=1', hash: '#readme' }

Slide 57

Slide 57 text

Named Captures (Stage 3) const urlRegExp = /^(?(? http[s]?|ftp):\/)? \/?(?[^:\/\s]+)(? (?:\/\w+)*\/)(? [\w\-\.]+[^#?\s]+)(? .*)?(?#[\w\-]+)? $/ const url = 'https://commits.com/8b48e3/diff?w=1#readme' const pattern = '$://github.com/$' const replaced = url.replace(urlRegExp, pattern) console.log(replaced) // <- 'https://github.com/diff'

Slide 58

Slide 58 text

Named Captures (Stage 3) const urlRegExp = /^(?(? http[s]?|ftp):\/)? \/?(?[^:\/\s]+)(? (?:\/\w+)*\/)(? [\w\-\.]+[^#?\s]+)(? .*)?(?#[\w\-]+)? $/ const duplicateRegExp = /^(.*)=\1$/ const duplicateRegExp = /^(?.*)=\k$/u duplicateRegExp.test('a=b') // <- false duplicateRegExp.test('a=a') // <- true duplicateRegExp.test('aa=a') // <- false duplicateRegExp.test('bbb=bbb') // <- true

Slide 59

Slide 59 text

Unicode Escapes (Stage 3) /^\p{Script=Greek}$/u.test('π') // <- true /^\P{Script=Greek}$/u.test('π') // <- false

Slide 60

Slide 60 text

Lookbehind Assertions (Stage 3) /\d+/.test('¥1245') // <- true /(?

Slide 61

Slide 61 text

Lookbehind Assertions (Stage 3) /\d+/.test('¥1245') // <- true /(?

Slide 62

Slide 62 text

Class Decorators (Stage 2) @pure @decorators.elastic() class View { @throttle(200) reconcile() { } }

Slide 63

Slide 63 text

Class Decorators (Stage 2) @pure @decorators.elastic() class View { @throttle(200) reconcile() { } } function readonly({ descriptor, ...rest }) { return { ...rest, descriptor: { ...descriptor, writable: false } } }

Slide 64

Slide 64 text

Promise#finally (Stage 2) showSpinner() fetch(productUrl) .then(renderProduct) .then( hideSpinner, hideSpinner )

Slide 65

Slide 65 text

Promise#finally (Stage 2) showSpinner() fetch(productUrl) .then(renderProduct) .finally( hideSpinner )

Slide 66

Slide 66 text

Future of JavaScript

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

Prepack

Slide 78

Slide 78 text

Resources ponyfoo.com/articles/es6 ponyfoo.com/articles/understanding-javascript-async-await ponyfoo.com/articles/regular-expressions-post-es6 ponyfoo.com/articles/standard ponyfoo.com/articles/javascript-asynchronous-iteration-proposal ponyfoo.com/books/practical-modern-javascript/chapters prop-tc39.now.sh github.com/tc39/proposals twitter.com/nzgb

Slide 79

Slide 79 text

Thanks!