the beautiful simplicity of es2015
TRANSCRIPT
The Beautiful Simplicityof ES2015
Brandon Belvin
What is ES2015?
● Code-named "Harmony;" contains many improvements that were slated for the fourth edition of ECMAScript (commonly known as JavaScript)
● Began in 2008, but was scaled back and delayed after dissent
● Re-emerged in 2011 to become the sixth edition, known as ES6
● Finalized in June 2015, renamed to ES2015
● Annual updates planned with ES2016 and ES2017 roadmapped
But what makes ES2015 so great?...
Arrow Functions
Features
● Terse, yet expressive
● Bound to lexical scope
● Make great sense when following functional programming
What They Solve
● Perfect for small, in-line anonymous functions
● Less var self = this; and.bind(this)
[1,2,3].reduce((acc,val) => acc + val);
[1,2,3].reduce(function(acc, val) {
return acc + val;
});
Arrow Functions
ES6
ES5
[1,2,3].reduce((acc,val) => acc + val);
Arrow Functions
[1,2,3,4,5,6].filter(val => val !== 5) //[1,2,3,4,6]
.map((val, i) => val * i) //[0,2,6,12,24]
.reduce((prev, cur) => prev + cur); //44
(This is in no way a contrived example… It's completely serious.)
Template Strings
Features
● Native interpolation
● Multi-line strings
● Custom template processors
What They Solve
● No need to escape tick or quote
● No more:
'Looped ' + count + ' times'
'foo\n' +'bar\n' +'baz'
`The time and date is ${ new Date().toLocaleString() }`
var apples = 5;var text = 'Bob ate ' + apples + ' of his apples!';console.log(text);// Bob ate 5 of his apples!
Template Strings
ES5
ES6var howMany = apples => apples > 4 ? 'so many' : 'a few';var apples = 5;var text = `Bob ate ${ howMany(apples) } apples!`;console.log(text);// Bob ate so many apples!
Template StringsMulti-linevar multiLineText = `This ismulti-line and continuesuntil the nextbacktick`;
// This is// multi-line and continues// until the next// backtick
Function Interpolationvar list = [ 1, 2, 3 ];var template = `<div><ul>${list.map(num => `<li>${num}</li>`).join('\n')}</ul></div>`;
// <div><ul>// <li>1</li>// <li>2</li>// <li>3</li>// </ul></div>
Assignment Destructuring
Features
● Easier variable assignment
● Can access deep properties in objects
● Assignment and index skipping for arrays
What They Solve
● No more huge blocks of assignment boilerplate
● Destructuring as a parameter list
var { baseUrl, body, params: { id } } = request;
Assignment Destructuring
ES5var baseUrl = request.baseUrl;var body = request.body;var pageId = request.params.id;
ES6var { baseUrl, body, params: { id: pageId } } = request;
Default and Rest Parameters, Spread Operator
Features
● Can set a default argument value
● Collect multiple arguments into an array
● Can also destructure arrays
What They Solve
● Set a default value rather than checking for existence inside the function
● Can be used instead of the arguments object (which isn't a real array)
● Can replace the .apply() function
function foo (bar=12, ...rest) { var ary = [1, 2, ...rest]; }
Default and Rest ParametersES5function sum() { if (!arguments.length) { return 0; } var args = Array.prototype.slice.call(arguments); var base = args.shift(); return args.reduce(function (prev, val) { return prev + val; }, base);} // 8 lines inside sum()
sum(); // 0sum(5); // 5sum(1,2,3,4,5,6,7); // 28
Default and Rest ParametersES5 (Improved)function sum() { var args = Array.prototype.slice.call(arguments); var base = args.shift(); return args.reduce(function (prev, val) { return prev + val; }, base || 0);} // 5 lines inside sum()
sum(); // 0sum(5); // 5sum(1,2,3,4,5,6,7); // 28
Default and Rest ParametersES6function sum(base = 0, ...vals) { return vals.reduce((prev, val) => prev + val, base);} // 1 line inside sum()
sum(); // 0sum(5); // 5sum(1,2,3,4,5,6,7); // 28
var x = new (Date.bind.apply(Date, [null, 2015, 9, 23]));console.log(x.toDateString());// Fri Oct 23 2015
Spread Operator
ES5
ES6var x = new Date(...[2015, 9, 23]);console.log(x.toDateString());// Fri Oct 23 2015
(Hat-tip to Nicolas Bevacqua for this example)
Promises
Features
● Allows for more narrative asynchronous code
● "Proper" exception handling
● Easier to follow for complex asynchronous interactions through chaining
What They Solve
● Eliminate "callback spaghetti"
● Can throw exception rather than return it in callback
fetch('foo').then(res => {}).catch(err => {})
Callback ExampleUser.findById('bob_appleseed', function(err, user) { if (err) { return console.log(`error: ${ err }`); } user.apples = user.apples - 5;
user.save(function(err, user) { if (err) { return console.log(`error: ${ err }`); } console.log(`Bob now has ${ user.apples } apples`); });});
PromisesUser.findById('bob_appleseed').exec() .then(user => { user.apples = user.apples - 5;
return user.save(); // returning a promise here }) .then(user => { console.log(`Bob now has ${ user.apples } apples`); }) .catch(err => { // Only need one catch for this chain console.log(`error: ${ err }`); });
PromisesExtra Features
Promises.all([ fetch('api.random.org'), fetch('api.random.org') ]) .then(randoms => randoms.reduce((prev, val) => prev + val, 0) / randoms.length; }) .catch(err => `Randoms request failed with error: ${ err }`);
Promise.all() - Wraps an array of Promises in a Promise that either resolves when all the dependencies resolve, or rejects if any of the dependencies reject.
● Useful when a function should only run after a number of parallel async operations are complete
PromisesExtra Features
Promise.race([ fetch('/resource-that-may-take-a-while'), new Promise((resolve, reject) => setTimeout(() => reject(new Error('request timeout')), 5000) )]).then(response => console.log(response)).catch(error => console.log(error));
Promise.race() - Accepts an array of Promises and settles with the value of the first to complete.
● Can be used to handle timeout of a Promise we otherwise have no control over:
(Another very grateful hat-tip to Nicolas Bevacqua for this example)
And this only scratches the surface...
Assignment Destructuring
Spread Operator
Rest Parameters
Arrow Functions
Template Strings
Object Literals
Classes
Let and ConstSymbols
IteratorsGenerators
Promises
Maps/WeakMaps
Sets/WeakSets
Proxies
Reflection
Modules
How to use ES2015 today
100% support is still a long way off, but you can use most of the enhancements today.
Built-in Support:
● Node v4 (more with --harmony flag)
● Chrome● Firefox● Microsoft Edge
Transpiler:
● Babel (babeljs.io)
● Traceur (google/traceur-compiler)
Where to learn ES2015
Blogs & Writing:
● PonyFoo (ponyfoo.com)
● JavaScript Scene (medium.com/javascript-scene)
● Babel Docs (babeljs.io/docs/learn-es2015)
Docs & Resources:
● Mozilla Developer Network (MDN)
● Learn Harmony (learnharmony.org)
Brandon Belvin
@PizzaBrandon
TwitterGitHub