In 2016, we’ll be publishing ES 2016, and ES 2015 will be missing a lot of stuff that ES 2016 has
– Domenic Denicola
class Cat {
constructor(name) {
this.name = name
}
speak() {
console.log('Bark, woof')
}
attack(enemy) {
console.log('Feed me')
}
}
function Cat(name) {
this.name = name
}
Cat.prototype.speak = function() {
console.log('Bark, woof')
}
Cat.prototype.attack = function(enemy) {
console.log('Feed me')
}
function animalMood(mood = 'Happy', animal = 'Taniwha') {
return mood + ' ' + animal
}
animalMood() // "Happy Taniwha"
animalMood('Angry') // "Angry Taniwha"
animalMood(undefined, 'Snake') // "Happy Snake"
animalMood('Yappy', 'Dog') // "Yappy Dog"
function animalMood() {
var mood = arguments[0] === undefined ? 'Happy' : arguments[0]
var animal = arguments[1] === undefined ? 'Taniwha' : arguments[1]
return mood + ' ' + animal
}
class CatAPI {
fetch(limit) {
// ...
}
fetchAll() {
// ...
}
}
export default new CatAPI()
import cats from './cat-api'
import { foo, baz } from './utils'
let cats = cats.fetchAll().map(foo)
export {
foo: function() {},
bar: function() {},
baz: function() {}
}
main.js
cat-api.js
utils.js
let square = x => x * x
// Implicit return
// Single parameter; optional brackets
[1, 2, 3, 4].reduce((p, c) => p + c)
// Brackets for multiple params
setTimeout(() => {
console.log('Mathematical!')
})
// No implicit return with block syntax
var square = function (x) {
return x * x
}
[1, 2, 3, 4].reduce(function (p, c) {
return p + c
})
setTimeout(function() {
console.log('Mathematical!')
})
var lemongrab = {
punishment: 'One million years dungeon!',
givePunishment: function() {
setTimeout(function() {
// this === window/global
console.log(this.punishment) // undefined :(
}, 1000)
}
}
this
bindingvar lemongrab = {
punishment: 'One million years dungeon!',
givePunishment: function() {
var _this = this; // yuck
setTimeout(function() {
console.log(_this.punishment) // One million years dungeon!
}, 1000)
}
}
this
bindingvar lemongrab = {
punishment: 'One million years dungeon!',
givePunishment: function() {
setTimeout(function() {
console.log(this.punishment) // One million years dungeon!
}.bind(this) /* ick */, 1000)
}
}
this
bindingvar lemongrab = {
punishment: 'One million years dungeon!',
givePunishment: function() {
setTimeout(() => {
// this === lemongrab
console.log(this.punishment) // One million years dungeon!
}, 1000)
}
}
this
bindingfor (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
}, 1000)
}
// 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
JavaScript's scoping can cause unexpected behaviour
wat
for (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(function () {
console.log(i)
}, 1000)
})(i)
}
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
We tend to use closures to work around this
yuck
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
}, 1000)
}
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
But what we really need is block scope
\o/
var numbers = [1, 2, 3, 4]
[for (n of numbers) n * 2]
// [2, 4, 6, 8]
[for (n of numbers) if (n < 3) n]
// [1, 2]
[for (n of numbers) if (n > 2) n + 1]
// [4, 5]
var numbers = [1, 2, 3, 4]
numbers.map(function(n) {
return n * 2
})
// [2, 4, 6, 8]
numbers.filter(function(n) {
return n < 3
})
// [1, 2]
numbers.filter(function(n) {
return n > 2
}).map(function(n) {
return n + 1
})
// [4, 5]
Array comprehensions
Array.map / Array.filter
var cows = ['bertha', 'hoani', 'daisy', 'harold', 'tama']
console.log(`I have ${cows.length} cows, but I want ${cows.length + 2}!
My favourite is ${cows[0]}.`)
// "I have 5 cows, but I want 7!
//
// My favourite is bertha."
// Array matching
let [x, y] = [22, 18]
console.log(x, y) // 22, 18
let [a, , b] = [1, 2, 3]
console.log(a, b) // 1, 3
// Using the splat operator
let [a, b, ...c] = [1, 2, 3, 4, 5]
console.log(a, b, c) // 1, 2, [3, 4, 5]
// Object matching
{ a, b } = { a: 'foo', b: 'bar' }
console.log(a, b) // "foo", "bar"
Reflection API