aka ES6
my favourite parts
do you have your laptop with you?
stop coding (or facebooking) and follow these slides at andreduarte.info
these slides contain code and you can play with it by clicking try me
André Duarte
Senior Front-end Developer
@ Blip - Paddy Power Betfair
Mostly building Betfair Sportsbook mobile web application
1997
1998
1999
RIP
2009
2011
2015
2016
ES1
ES2
ES3
ES4
ES5
ES5.1
ES2015
ES2016
First versions. Mostly tried to solve the mess between Netscape's JavaScript and Microsoft's JScript.
We could have had modules, classes, everything!
But it was abandoned.
The stable versions.
"Strict mode" and so on.
Started by recovering a lot of the ES4 proposals.
Yearly iterations from now on.
0%
100%
Chrome 52 / Opera 39
97%
Node 6
92%
Edge 14
95%
Firefox 48
91%
Safari 9
54%
IE 11
11%
71%
71%
Babel
Babel
let a = 12
function myFunction() {
console.log(a) // 12
console.log(b) // Reference Error Exception
let b = 13
if (true) {
let c = 14
console.log(b) // 13
}
console.log(c) // Reference Error Exception
}
var a = 12
function myFunction() {
console.log(a) // 12
console.log(b) // undefined
var b = 13
if (true) {
var c = 14
console.log(b) // 13
}
console.log(c) // 14
}
const PI = 3.14
var r = 5
// 2 + 2 != 5
PI = 3.15 // Read only exception
var area = PI * r * r
console.log(area)
var PI = 3.14
var r = 5
// 2 + 2 = 5
PI = 3.15
var area = PI * r * r
console.log(area) // 78.75
const config = {
name: 'andré'
}
config.name = 'el pixel'
console.log(config.name) // el pixel
Object.freeze(config)
config.name = 'andré'
console.log(config.name) // still el pixel
function myFunction (x = 1, y = 2, z = 1 + 2) {
console.log(x, y, z)
}
myFunction(6, 7) // 6 7 3
function myFunction (x, y, z) {
x = x === undefined ? 1 : x
y = y === undefined ? 2 : y
z = z === undefined ? 3 : z
console.log(x, y, z)
}
myFunction(6, 7) // 6 7 3
function myFunction (a, b) {
}
myFunction(1, 2, 3, 4, 5) // 3, 4, 5
function myFunction (a, b, ...extraArgs) {
console.log(extraArgs)
}
// note: myFunction.length returns the number of arguments expected by the function
// note: arguments is an array-like object, but not really an array,
// so don't expect it to inherit functions from Array.prototype
// such as Array.slice()
var extraArgs = Array.prototype.slice.call(arguments, myFunction.length)
console.log(extraArgs)
let str1 = "Hello world!"
let str2 = `Hello world!`
console.log(str1 === str2) //true
let str3 = "'Hello\nMy name \"is\" André', he said."
let str4 = `'Hello
My name "is" André', he said.`
// The only character that needs escaping is the ` itself
let event = 'Pixels Camp'
let today = new Date()
let str5 = "I'm loving " + event + ' ' + today.getFullYear() + "!"
let str6 = `I'm loving ${event} ${today.getFullYear()}!`
// I'm loving Pixels Camp 2016!
const someConstant = 3.14
let name = 'john'
let surname = 'smith'
let oldObject = {
someConstant: someConstant,
name: name,
surname: surname,
saySomething: function saySomething() {
console.log(`Hello ${this.name} ${surname}!`)
}
}
oldObject.saySomething()
const someConstant = 3.14
let name = 'john'
let surname = 'smith'
let newObject = {
someConstant,
name,
surname,
saySomething () {
console.log(`Hello ${this.name} ${surname}!`)
}
}
newObject.saySomething()
let presentation = {
title: 'ES2015',
duration: '45min'
}
let title = presentation.title
let duration = presentation.duration
let {title, duration} = presentation
let {title: foo, duration: bar} = presentation
console.log(foo) // ES2015
console.log(bar) // 45min
function tweetThis(message, optionalConfigs) {
let when = optionalConfigs.when || Date.now()
let shareToFacebook = optionalConfigs.shareToFacebook || false
// ...
}
function newTweetThis(message, {when, shareToFacebook}) {
when = when || Date.now()
shareToFacebook = shareToFacebook || false
// ...
}
function es6TweetThis(message, {when = Date.now(), shareToFacebook = false}) {
// Just code!
}
function circleArea(pi, r) {
return pi * r * r
}
let a = ['a', 'ab', 'abc', 'abcd']
let aCount = a.map(function (input) {return input.length})
console.log(aCount) // 1, 2, 3, 4
let circleAreaShort = (pi, r) => {
return pi * r * r
}
let circleAreaShorter = (pi, r) => pi * r * r
conosle.log(circleArea(3.14, 3), circleAreaShort(3.14, 3), circleAreaShorter(3.14, 3))
// 28.26, 28.26, 28.26
let bCount = a.map(input => input.length)
console.log(bCount) // 1, 2, 3, 4
function TestModule() {
'use strict';
var self = this;
this.words = ['i', 'love', 'pixels', 'camp'];
this.sentence = '';
this.betterSentence = '';
}
this.buildBetterSentence = function () {
this.words.forEach((word) => {
this.betterSentence += word + ' ';
});
};
this.buildSentence = function () {
this.words.forEach(function (word) {
// this would be undefined
self.sentence += word + ' ';
});
};
class Person {
}
let student = new Student('john')
student.printName()
Student.sayHello(student)
function Person(name) {
this.name = name
}
Person.prototype.printName = function () {
console.log(this.name)
}
Person.sayHello = function (person) {
console.log(`Hello ${person.name}!`)
}
let student = new Person('André')
student.printName()
Student.sayHello(student)
constructor(name) {
this.name = name
}
printName() {
console.log(this.name)
}
static sayHello(student) {
console.log(`Hello ${person.name}!`)
}
class Person {
constructor(name) {
this.name = name
}
printName() {
console.log(this.name)
}
}
function Person(name) {
this.name = name
}
Person.prototype.printName = function () {
console.log(this.name)
}
Person.call(this, name)
function Student(name, school) {
this.school = school
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
Student.prototype.printSchool = function () {
console.log(this.school)
}
let student = new Student('André', 'FEUP')
student.printName()
student.printSchool()
class Student extends Person {
}
constructor(name, school) {
super(name)
this.school = school
}
printSchool() {
console.log(this.school)
}
const apiURL = 'https://api.discogs.com'
const daftPunkId = 1289
const myCurrency = 'EUR'
function fetchReleasesFromArtist(artistId) {
return fetch(`${apiURL}/artists/${artistId}/releases?sort=year`)
.then(res => res.json()).then(res => res.releases)
}
function fetchReleaseDetails(releaseId) {
return fetch(`${apiURL}/releases/${releaseId}?curr_abbr=${myCurrency}`)
.then(res => res.json())
}
fetchReleasesFromArtist(daftPunkId)
.then(releases => fetchReleaseDetails(releases[0].id))
.then(release => {
console.log(`You can get ${release.title}
for €${Math.round(release.lowest_price, 2)}.`)
})
constants.js
services.js
core.js
const apiURL = 'https://api.discogs.com'
const daftPunkId = 1289
const myCurrency = 'EUR'
function fetchReleasesFromArtist(artistId) {
return fetch(`${apiURL}/artists/${artistId}/releases?sort=year`)
.then(res => res.json()).then(res => res.releases)
}
function fetchReleaseDetails(releaseId) {
return fetch(`${apiURL}/releases/${releaseId}?curr_abbr=${myCurrency}`)
.then(res => res.json())
}
fetchReleasesFromArtist(daftPunkId)
.then(releases => fetchReleaseDetails(releases[0].id))
.then(release => {
console.log(`You can get ${release.title}
for €${Math.round(release.lowest_price, 2)}.`)
})
bundle.js
function () {
}())
const apiURL = 'https://api.discogs.com'
const daftPunkId = 1289
const myCurrency = 'EUR'
function fetchReleasesFromArtist(artistId) {
return fetch(`${apiURL}/artists/${artistId}/releases?sort=year`)
.then(res => res.json()).then(res => res.releases)
}
function fetchReleaseDetails(releaseId) {
return fetch(`${apiURL}/releases/${releaseId}?curr_abbr=${myCurrency}`)
.then(res => res.json())
}
fetchReleasesFromArtist(daftPunkId)
.then(releases => fetchReleaseDetails(releases[0].id))
.then(release => {
console.log(`You can get ${release.title}
for €${Math.round(release.lowest_price, 2)}.`)
})
constants.js
services.js
core.js
export const apiURL = 'https://api.discogs.com'
export const daftPunkId = 1289
export const myCurrency = 'EUR'
import {apiURL, myCurrency} from "./constants"
function fetchReleasesFromArtist(artistId) {
return fetch(`${apiURL}/artists/${artistId}/releases?sort=year`)
.then(res => res.json()).then(res => res.releases)
}
function fetchReleaseDetails(releaseId) {
return fetch(`${apiURL}/releases/${releaseId}?curr_abbr=${myCurrency}`)
.then(res => res.json())
}
import {daftPunkId} from "./constants"
import api from "./services"
api.fetchReleasesFromArtist(daftPunkId)
.then(releases => api.fetchReleaseDetails(releases[0].id))
.then(release => {
console.log(`You can get ${release.title}
for €${Math.round(release.lowest_price, 2)}.`)
})
constants.js
services.js
core.js
const apiURL = 'https://api.discogs.com'
const daftPunkId = 1289
const myCurrency = 'EUR'
function fetchReleasesFromArtist(artistId) {
return fetch(`${apiURL}/artists/${artistId}/releases?sort=year`)
.then(res => res.json()).then(res => res.releases)
}
function fetchReleaseDetails(releaseId) {
return fetch(`${apiURL}/releases/${releaseId}?curr_abbr=${myCurrency}`)
.then(res => res.json())
}
fetchReleasesFromArtist(daftPunkId)
.then(releases => fetchReleaseDetails(releases[0].id))
.then(release => {
console.log(`You can get ${release.title}
for €${Math.round(release.lowest_price, 2)}.`)
})
export default {fetchReleasesFromArtist, fetchReleaseDetails}
not much...
Math.pow(2, 3) // 8
exponential operator
let newPow = 2 ** 3
console.log(newPow) // 8
Array.prototype.includes
let arr = ['a', 'b', 'c']
let hasA = arr.indexOf('a') !== -1
let hasB = arr.includes('b') // true
let hasD = arr.includes('d') // false
// use fetch as a promise-based alternative to xhr
fetch('https://api.discogs.com/artists/1289/releases?sort=year&sort_order=desc')
.then(res => res.json())
.then(res => res.releases[0].id)
.then(releaseId => fetch(`https://api.discogs.com/releases/${releaseId}?curr_abbr=EUR`))
.then(res => res.json())
.then(release => {
console.log(`You can get ${release.title} for €${Math.round(release.lowest_price, 2)}.`)
})
async/await functions
ES 2017 / 2018 / etc.
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
}) // Welcome to callback hell
(async function getCheapestRecord() {
let fetchReleases = await fetch('https://api.discogs.com/artists/1289/releases?sort=year')
let releasesJson = await fetchReleases.json()
let releaseId = releasesJson.releases[0].id
let fetchDetails = await fetch(`https://api.discogs.com/releases/${releaseId}`)
let detailsJson = await fetchDetails.json()
console.log(`You can get ${detailsJson.title}
for €${Math.round(detailsJson.lowest_price, 2)}.`)
}());
already available on Chrome Canary and Babel
Tweet your questions to @onemanclapping
Presentation available at http://andreduarte.info
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
}) // Welcome to callback hell
new Promise( /* executor */ function(resolve, reject) { ... } )
A Promise
represents a value which may be available now, or in the future, or never.
Promise.prototype.then(function onFulfilled(value) { ... })
Promise.prototype.catch(function onRejected(reason) { ... })
Promise.all(iterable<Promise>).then(function allFulfilled(values) { ... })
Promise.race(iterable<Promise>).then(function firstFulfilled(value) { ... })
Executes the callback as soon as the promise is fulfilled.
Executes the callback if anything goes wrong.
Returns a promise that resolves when all promises are fulfilled.
Returns a promise that resolves as soon as one promise is fulfilled.
// use fetch as a promise-based alternative to xhr
fetch('https://api.discogs.com/artists/1289/releases?sort=year&sort_order=desc')
.then(res => res.json())
.then(res => res.releases[0].id)
.then(releaseId => fetch(`https://api.discogs.com/releases/${releaseId}?curr_abbr=EUR`))
.then(res => res.json())
.then(release => {
console.log(`You can get ${release.title} for €${Math.round(release.lowest_price, 2)}.`)
})
function waitAndPrint(msg) {
return new Promise(resolve => {
setTimeout(() => {
console.log(msg)
resolve()
}, 3000)
})
}
function fetchSomeData() {
let url = 'https://api.discogs.com/artists/1289/releases?sort=year&sort_order=desc'
return fetch(url).then(res => res.json())
}
Promise.all([fetchSomeData(), fetchSomeData()])
.then(data => {
console.log('Data is here. Comparing content.')
let isDataEqual = data[0].releases[0].id === data[1].releases[0].id
return isDataEqual
})
.then(waitAndPrint)
.then(() => {
console.log('Done!')
})
.catch(e => {
console.log('Something went wrong', e)
})
let set = new Set('Hello!!!')
console.log(set)
// [object Set] { ... }
console.log(...set)
// That's the spread operator ...
// H, e, l, o, !
console.log(set.has('e')) // true
console.log(set.size) // 5
set.add({})
set.delete('o')
let map = new Map()
let o = {n: 1}
map.set(o, 'object')
map.set(123, 'number')
console.log(map.has(123)) // true
console.log(map.get(o)) // 'object'
map.delete(123)
console.log(...map)
// [{n: 1}, 'object']
let array = [10, 20, 30]
for (let value of array) {
console.log(value)
}
let string = "boo"
for (let value of string) {
console.log(value)
}
let divs = document.querySelectorAll("div");
for (let value of divs) {
console.log(value.textContent)
}
let s1 = Symbol()
let s2 = Symbol()
console.log(s1 === s2) // false
console.log(typeof s1) // 'symbol'
let obj = {
[s1]: 'foo'
}
console.log(obj[s1]) // 'foo'
obj[Symbol.for('name')] = 'special name'
console.log(obj.name) // undefined
console.log(obj[Symbol.for('name')]) // 'special name'
let object = {
firstClassData: [1, 2],
secondClassData: [3, 4],
}
for (let value of object) {
console.log(value) // 1, 2, 3, 4
}
[Symbol.iterator]: function () {
let bigArray = this.firstClassData.concat(this.secondClassData)
let nextIndex = 0
return {
next() {
if (nextIndex < bigArray.length) {
return {
value: bigArray[nextIndex++],
done: false
}
} else {
return {
done: true
}
}
}
}
}
let pres = someService.getCurrentPresentation()
{
title: 'ES2015',
duration: '45min',
speaker: {
name: 'André Duarte',
handlers: {
twitter: 'onemanclapping',
github: 'onemanclapping'
}
}
}
let {
title: theTitle,
speaker: {
handlers: {
twitter: theTwitter
}
}
} = pres
console.log(`@${theTwitter} is presenting ${theTitle}.`)
// @onemanclapping is presenting ES2015.