ES 6: The Refined Parts Redux

ES 6: The Refined Parts Redux

An overview of my favorite core refinements in ECMAScript 6, the next major revision of the standard that governs JavaScript. This is an expanded version of my W3Conf talk. Presented at the August SF HTML5 meet-up.

92f971951ab517f93be7866f0cf28777?s=128

Kit Cambridge

August 22, 2013
Tweet

Transcript

  1. ECMAScript 6: The Re ned Parts Kit Cambridge

  2. Every technology has a story. The story provides the context

    for the nal product. Without a story, few decisions make sense.
  3. 1995 1999 2005 2009 2013

  4. 1995 1999 2005 2009 2013 Function expressions Regular expressions throw

    Array literals Object literals String, number, date methods try...catch switch instanceof in do...while ===
  5. 1995 1999 2005 2009 2013 Interfaces Pragmas Classes Namespaces Static

    type system goto ...rest Packages Lexical binding Block scope Generators Overloading Iterators Type annotations Strict mode Re ection
  6. 1995 1999 2005 2009 2013 Tighter regular expression, eval, error,

    and global object semantics Standardizing de facto behaviors Array extras New object re ection methods Strict mode Native JSON support get() set(value)
  7. 1995 1999 2005 2009 2013 Classes Template Literals Object Shorthands

    Proxies Modules Block Scope Destructuring Unicode Binary Data Collections Arrow Functions Symbols Generators Iterators Tail-Call Optimization ...rest ...spread Default parameters for...of Re ection Convenience methods
  8. “To ES 7...and beyond!” 1995 1999 2005 2009 2013

  9. Generators Suspend and resume execution at multiple locations .next(value) resumes

    execution yield suspends execution .throw(error) raises an exception at the suspended location
  10. function* fibonacci() { var [previous, current] = [0, 1]; while

    (1) { [previous, current] = [current, previous + current]; let isReset = yield current; if (isReset) { [previous, current] = [0, 1]; } } } function* distinguishes a generator from a function yield returns a generator object that can modify the generator’s state
  11. var generator = fibonacci(); generator.next(); // => { value: 1,

    done: false } generator.next(); // => { value: 2, done: false } generator.next(true); // => { value: 1, done: false } generator.throw(Error('Exceptional condition.')); // => Throws an error with the given message.
  12. What if the caller of .next() and .throw() could resume

    execution when an asynchronous operation completed? github.com/kriskowal/q github.com/visionmedia/co
  13. var {name, address} = request.payload; Q.async(function* createAccount() { let account

    = null; try { account = yield Account.getByAddress(address); } catch (exception) { if (exception.response.code != 404) { throw exception; } } if (account) { throw new Error('This address is already in use.'); } account = new Account(); account.update({ name, address }); yield account.save(); });
  14. Collections Map Set WeakMap WeakSet

  15. Collections All collections support sub-linear lookup times Sets can remove

    duplicates in linear time Maps and Sets enumerate entries in insertion order WeakMaps and WeakSets use weak references to allow for garbage collection var unique = [...new Set([1, 2, O, 2, 3, 'A', 'B', O, 'C', 'C', 'D'])]; // => [1, 2, O, 3, 'A', 'B', 'C', 'D']
  16. // Leak-free element storage engine. var storage = new WeakMap();

    function store(element, name, value) { // Create the element data store if // it doesn't exist. if (!storage.has(element)) { storage.set(element, new Map()); } // Associate the name and value with // the element. storage.get(element).set(name, value); return element; }
  17. function retrieve(element, name) { if (!storage.has(element)) { return; } return

    storage.get(element).get(name); } function unstore(element, name) { if (!storage.has(element)) { return; } let data = storage.get(element); let value = data.get(name); data.delete(name); return value; }
  18. Symbols Unique, private object property names A memory-e cient alternative

    to the revealing module pattern [] distinguishes between symbols and strings
  19. let uri = Symbol(), clientId = Symbol(); let clientSecret =

    Symbol(); function OAuthClient(baseURI, id, secret) { this[uri] = baseURI; this[clientId] = id; this[clientSecret] = secret; } OAuthClient.prototype = { request(endpoint, credentials) { let id = this[clientId]; let secret = this[clientSecret]; return new Request(this[uri], endpoint). sign({ id, secret }, credentials); } };
  20. Destructuring Assignment Pull values from objects and arrays Swap variables

    Parse complex structures in a single statement Specify default values for arguments
  21. var {parse, stringify} = JSON; const pattern = /^(?:(\d{3})-)?(\d{3}-\d{4})$/; var

    [, areaCode = 415, local] = pattern.exec(phone); [left, right] = [right, left]; let getHeaders = ({'request': {headers}}) => headers
  22. var poets = [{ "name": "T.S. Eliot", "works": [{ "title":

    "The Love Song of J. Alfred Prufrock", "date": 1915 }, { "title": "Rhapsody on a Windy Night", "date": 1917 }] }, { "name": "Ezra Pound", "works": [{ "title": "Ripostes", "date": 1912 }] }]; var [{'name': author, 'works': [, {title, date}]}] = poets; `"${title}", by ${author}, was published in ${date}.` // => '"Rhapsody on a Windy Night", by T.S. Eliot, was published in 1917.'
  23. function request(uri = '', { method = 'GET', qs =

    {}, headers = {}, body, form, auth, json, maxRedirects = 10, jar = false }) { // ... } Default parameter syntax Destructuring with default values
  24. Shorthand Syntax Initializers Method De nitions var name = 'Kit';

    var occupation = 'programmer'; var person = { 'name': name, 'occupation': occupation }; var name = 'Kit'; var occupation = 'programmer'; var person = { name, occupation };
  25. Shorthand Method Template Literal Getter New API Method var years

    = Symbol(); function Speaker(name) { this.name = name; this[years] = 0; } Speaker.prototype = { speak(message) { return `${this.name}: ${message}`; }, get age() { return this[years]; }, set age(value) { if (Number.isFinite(value)) { this[years] = value; } } }
  26. ...spread Expand an array of arguments without altering this Supports

    constructors Convenient syntax for merging arrays and array-like objects Convert any object with a length property into an array
  27. ...rest Supplants the arguments object Always returns an array, even

    when parameters are omitted Natural syntax for variadic functions Only valid as the last parameter of a function
  28. function getCredentials({ 'request': { 'headers': { authorization } } })

    { let [scheme , ...components] = authorization.split(' '); if (scheme != 'Basic' || components.length > 1) { return null; } let [credentials] = components; credentials = new Buffer(credentials, 'base64').toString('utf8'); if (!credentials.contains(':')) { return null; } let pattern = /^([^:]+):(\w+)$/; let [, name = '', password = ''] = pattern.exec(credentials) || []; return { name, password }; } getCredentials(request); // => { name: 'Kit', password: '...' }
  29. Tagged Template Literals `-delimited, multiline strings with embedded expressions Handlers

    may perform additional processing Contextual escaping Build extensible template languages
  30. function escape(values, ...substitutions) { let { raw, 'raw': { length

    } } = values; let results = ''; for (let index = 0; index < length; index++) { results += raw[index]; if (index + 1 == length) { break; } results += String(substitutions[index]).replace(/[&<>"']/g, (match) => `&#x${match.codePointAt(0).toString(16)};`); } return results; } let name = 'Kit<script>alert(1)</script>'; escape`<span class="name">${name}</span>`; // => '<span class="name">Kit&#x3c;script&#x3e;alert(1)&#x3c;/ script&#x3e;</span>'
  31. Block Scope Lexical declarations with let and const let introduces

    meaningful semantics for blocks Function declarations are now supported within blocks const declarations may not be reassigned
  32. // The problem. for (var length = 2; length--;) {

    var dimension = length ? 'Width' : 'Height'; // Both methods will report the element's height. $['get' + dimension] = function getDimension(element) { return element['offset' + dimension]; }; } // The ES 6 solution. for (var length = 2; length--;) { let dimension = length ? 'Width' : 'Height'; $['get' + dimension] = function getDimension(element) { return element['offset' + dimension]; } }
  33. Gotchas

  34. function getMood({ 'actions': { isSinging } }) { // Syntax

    error. Lexical declarations must be nested // within blocks. if (isSinging) let mood = 'greatlyImproved'; // Syntax error. Constants cannot be re-declared. const isWritingCode = true; const isWritingCode = false; // Type error in strict mode. Constants are read-only. isWritingCode = false; // Syntax error. `var` declarations cannot shadow // `let` and `const` declarations. var isWritingCode = true; }
  35. => Functions Parentheses not required for single-parameter functions Blocks not

    required for single-value expressions Runtime semantics identical to bound functions [1, 2, 3, 4, 5].filter(value => value % 2); // => [1, 3, 5] let identify = (() => ({ 'toString': () => { return 'Kit'; } }); `${identify()} <3s ES 6.`; // => 'Kit <3s ES 6.'
  36. Something for everyone. Shorthand Syntax Data Structures Modularity Core Re

    nements Tooling
  37. When can I use...? kangax.github.com/es5-compat-table/es6 “Enable Experimental JavaScript” in about:

    ags Some non- standard features --harmony ag
  38. Continuum Traceur es6ify benvie.github.com/ continuum github.com/google/ traceur-compiler github.com/thlorenz/ es6ify

  39. Follow @esdiscuss Catch up at esdiscuss.org

  40. Thank you! @kitcambridge Black Pearl Systems