Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Kit Cambridge

August 22, 2013
Tweet

More Decks by Kit Cambridge

Other Decks in Technology

Transcript

  1. ECMAScript 6: The Re ned
    Parts
    Kit Cambridge

    View full-size slide

  2. Every
    technology
    has a story.
    The story provides
    the context for the
    nal product.
    Without a story, few
    decisions make
    sense.

    View full-size slide

  3. 1995 1999 2005 2009 2013

    View full-size slide

  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
    ===

    View full-size slide

  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

    View full-size slide

  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)

    View full-size slide

  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

    View full-size slide

  8. “To ES 7...and beyond!”
    1995 1999 2005 2009 2013

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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.

    View full-size slide

  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

    View full-size slide

  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();
    });

    View full-size slide

  14. Collections
    Map
    Set
    WeakMap
    WeakSet

    View full-size slide

  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']

    View full-size slide

  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;
    }

    View full-size slide

  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;
    }

    View full-size slide

  18. Symbols
    Unique, private object property names
    A memory-e cient alternative to
    the revealing module pattern
    [] distinguishes between symbols and
    strings

    View full-size slide

  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);
    }
    };

    View full-size slide

  20. Destructuring
    Assignment
    Pull values from objects and arrays
    Swap variables
    Parse complex structures in a single statement
    Specify default values for arguments

    View full-size slide

  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

    View full-size slide

  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.'

    View full-size slide

  23. function request(uri = '', {
    method = 'GET',
    qs = {},
    headers = {},
    body,
    form,
    auth,
    json,
    maxRedirects = 10,
    jar = false
    }) {
    // ...
    }
    Default
    parameter
    syntax
    Destructuring
    with default
    values

    View full-size slide

  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 };

    View full-size slide

  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;
    }
    }
    }

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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: '...' }

    View full-size slide

  29. Tagged Template
    Literals
    `-delimited, multiline strings
    with embedded expressions
    Handlers may perform additional processing
    Contextual escaping
    Build extensible template languages

    View full-size slide

  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) => `${match.codePointAt(0).toString(16)};`);
    }
    return results;
    }
    let name = 'Kitalert(1)';
    escape`${name}`;
    // => 'Kit<script>alert(1)</
    script>'

    View full-size slide

  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

    View full-size slide

  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];
    }
    }

    View full-size slide

  33. 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;
    }

    View full-size slide

  34. => 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.'

    View full-size slide

  35. Something for
    everyone.
    Shorthand Syntax
    Data Structures
    Modularity
    Core Re nements
    Tooling

    View full-size slide

  36. When can I use...?
    kangax.github.com/es5-compat-table/es6
    “Enable
    Experimental
    JavaScript” in
    about: ags
    Some non-
    standard
    features
    --harmony
    ag

    View full-size slide

  37. Continuum
    Traceur
    es6ify
    benvie.github.com/
    continuum
    github.com/google/
    traceur-compiler
    github.com/thlorenz/
    es6ify

    View full-size slide

  38. Follow @esdiscuss
    Catch up at esdiscuss.org

    View full-size slide

  39. Thank you!
    @kitcambridge
    Black Pearl Systems

    View full-size slide