or
or
Everything in the official ES2015 Spec (formerly known as ES6)
Some proposals from the ES2016 Spec (ES7)
* European Computer Manufacturer Association
Which brings us to...
DA FUQ?
// ES5
Elsa.on('stress', function () {
// handle stress (badly);
});
['Anna', 'Hans', 'Sven'].map(function () {
// ...
});
fetch('https://icecastle/elsa')
.then(function (elsa) {
// Movie ends early...
})
.catch(function (error) {
// Drama ensues...
});
// ES2015
Elsa.on('stress', () => {
// handle stress (badly);
});
['Anna', 'Hans', 'Sven'].map(() => {
// ...
});
fetch('https://icecastle/elsa')
.then((elsa) => {
// Movie ends early...
})
.catch((error) => {
// Drama ensues...
});
// ES2015
this.on('stress', () => {
this.handleStressBadly;
});
['Anna', 'Hans'].map((character) => {
this.singWith(character);
});
fetch('https://icecastle/elsa')
.then((elsa) => {
this.movieEnds();
})
.catch((error) => {
this.moarDrama();
});
// ES5
let elsa = this;
elsa.on('stress', function () {
elsa.handleStressBadly;
});
['Anna', 'Hans'].map(function (character) {
this.singWith(character);
}, this);
fetch('https://icecastle/elsa')
.then(function (elsa) {
this.movieEnds();
}.bind(this))
.catch(function (error) {
this.moarDrama();
}.bind(this));
// Arrow functions can get even shorter! Note the missing parens
// around the parameters, and the missing braces around the body,
// and the implicit return for the first statement:
[1, 2, 3, 4].map(x => x * x); // [1, 4, 9, 16]
// Missing parens only works with single parameters though,
// otherwise you need them:
[1, 2, 3, 4].map((element, index) => element * index);
[1, 2, 3, 4].map(() => 1);
// Noop in ES5:
function () { }
// Noop in ES2015:
() => {}
// Constant function in ES5:
function () {
return 1;
}
// Constant function in ES2015:
() => 1
// ES5
function Snowman (name) {
this.name = name;
}
Snowman.prototype.sayHi = function () {
return 'Hi everyone! I\'m'
+ this.name;
};
function Olaf () {
Snowman.call(this, 'Olaf');
}
Olaf.prototype = Object.create(Snowman.prototype);
Olaf.prototype.sayHi = function sayHi() {
return Snowman.prototype.sayHi.call(this)
+ ', and I like warm hugs';
};
var olaf = new Olaf();
olaf.sayHi();
// ES2015
class Snowman {
constructor (name) {
this.name = name;
}
sayHi () {
return `Hi everyone. I'm ${this.name}`
}
}
class Olaf extends Snowman {
constructor () {
super('Olaf');
}
sayHi () {
return `${super.sayHi()} and I like warm hugs!`
}
}
let olaf = new Olaf;
olaf.sayHi();
// ES5
function Snowman (name) {
this._name = name;
Object.defineProperty(this, 'name', {
get: function () {
return this._name;
},
set: function (newName) {
this._name = newName;
}
});
}
// ES2015
class Snowman {
constructor (name) {
this._name = name;
}
get name () {
return this._name;
}
set name (newName) {
this._name = newName;
}
}
The value of this inside an arrow function is bound to the this value outside of that arrow function.
true || false:
// ES5
var isBetterThanPeople = true;
var reindeer = getReindeer();
var reindeerOptions = {
isBetterThanPeople: isBetterThanPeople
};
reindeerOptions[reindeer.name] = reindeer;
// ES2015
let isBetterThanPeople = true;
let reindeer = getReindeer();
let reindeerOptions = {
isBetterThanPeople,
[reindeer.name]: reindeer
};
// ES5
var bestLyrics = '\n\
And it\'s nothing like I\'ve ever known before!\n\
Love is an open door!';
function finish (x) {
return 'We finish eat other\'s ' + x;
}
finish('sandwiches');
// ES2015
let bestLyrics = `
And it's nothing like I've ever known before!
Love is an open door!
`;
function finish (x) {
return `We finish eat other's ${x}`;
}
finish('sandwiches');
// ES5
var princesses = ['Elsa', 'Anna'];
var heirToArendelle = princesses[0];
// or
var heirToArendelle = _.first(princesses);
// ES2015
let princesses = ['Elsa', 'Anna'];
let [heirToArendelle] = princesses;
// ES5
var frozenFacts = {
producer: {
firstName: 'Peter',
lastName: 'Del Vecho'
},
runningTime: '102'
};
var producer = frozenFacts.producer;
var firstName = producer.firstName;
var length = frozenFacts.runningTime;
// ReferenceError:
var directorName = frozenFacts.director.name;
// ES2015
let frozenFacts = {
producer: {
firstName: 'Peter',
lastName: 'Del Vecho'
},
runningTime: '102'
};
let {
producer: { firstName },
runningTime: length
} = frozenFacts;
// No error!
let { director: { name }} = frozenFacts;
// name === undefined
true || false:
Trying to destructure a value out from a property that does not exist on an object will throw an error.
// ES5
function build (what) {
what = what || 'snowman';
return what;
}
build(); // 'snowman'
// ES2015
function build (what = 'snowman') {
return what;
}
build(); // 'snowman'
// ES5
function sweetChoreography (arguments) {
var guests = Array.prototype.slice.apply(arguments);
guests.forEach(function (guest) {
danceWith(guest);
});
}
sweetChoreography('Hans', 'Duke of Wesselton', 'Trolls');
// ES2015
function sweetChoreography (...guests) {
guests.forEach(guest => danceWith(guest));
}
sweetChoreography('Hans', 'Duke of Wesselton', 'Trolls');
// ES5
// Variable declarations:
var itGo = '';
// Constants:
var BOTHERED_BY_COLD = false;
// ES2015
// Variable declarations:
let itGo = '';
// Constants:
const BOTHERED_BY_COLD = false;
// ES5
for (var i = 0; i < 10; i += 1) {
element.click(function () {
console.log(i);
});
}
// 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
// ES2015
for (let i = 0; i < 10; i += 1) {
element.click(function () {
console.log(i);
});
}
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
// ES2015
const ARENDELLE = {
ruler: 'Elsa'
};
// Doesn't throw error:
ARENDELLE.ruler = 'Hans';
// const objects are not immutable:
const ARENDELLE = Object.freeze({
ruler: 'Elsa'
});
// Now throws:
ARENDELLE.ruler = 'Hans';
Objects that are created using const are immutable
true || false:
// ES5 (commonjs style)
// frozen.js:
module.exports = function frozen () {
console.log('best movie evah!!!');
}
module.exports.yay = [
'Anna',
'Elsa',
'Kristoff',
'Olaf'
];
// myapp.js
var frozen = require('frozen');
yay = frozen.yay;
frozen();
console.log(yay);
// ES2015
// frozen.js:
export default function frozen () {
console.log('best movie evah!!!');
}
export const yay = [
'Anna',
'Elsa',
'Kristoff',
'Olaf'
];
// myapp.js
import frozen, { yay } from 'frozen';
frozen();
// ES2015
// elsa.js
let conceal = Symbol();
class Elsa {
constructor (feelings) {
this[conceal] = feelings;
}
}
const feelings = 'BIG FEELS';
export default const elsa = new Elsa(feelings);
// app.js
import elsa from 'elsa';
// No way to access feelings (except reflection magic)
// ES2015:
// Special symbols:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
// ES2015:
fetch('https://icecastle/elsa')
.then(elsa => {
// Movie ends early...
})
.catch(error => {
// Drama ensues...
});
// ES2015:
Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN('NaN') // false
Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
'abcde'.includes('cd') // true
'let it go'.repeat(2) // 'let it go let it go'
Array.from(document.querySelectorAll('*')) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(7, 1) // [0,7,7]
[1, 2, 3].find(x => x == 3) // 3
[1, 2, 3].findIndex(x => x == 2) // 1
[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
['a', 'b', 'c'].entries() // iterator [0, 'a'], [1, 'b'], [2, 'c']
['a', 'b', 'c'].keys() // iterator 0, 1, 2
['a', 'b', 'c'].values() // iterator 'a', 'b', 'c'
Object.assign(Point, { origin: new Point(0,0) })
true || false:
Values assigned with symbols are completely private to their scope.
Array.prototype.includes
async/await
exponentiation operator
SIMD
decorators
observables
pipe operator
Pretty good support in browsers (see kangax tables)
Pretty good support in node
Excellent support using
transpilers/polyfills
(TypeScript or Babel, with core.js)