$30 off During Our Annual Pro Sale. View Details »

Future JavaScript: what is still missing?

Future JavaScript: what is still missing?

In recent years, JavaScript has grown considerably in size. In this talk, we’ll explore what features are still missing and what features may not be needed.

Axel Rauschmayer

March 11, 2019
Tweet

More Decks by Axel Rauschmayer

Other Decks in Programming

Transcript

  1. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 1/46
    Future JavaScript:
    Future JavaScript:
    what is still missing?
    what is still missing?
    JS Kongress, Munich, 2019-03-11
    JS Kongress, Munich, 2019-03-11

    View Slide

  2. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 2/46
    What is this talk about?
    What is this talk about?
    JavaScript has grown considerably in recent years, starting with
    ES6/ES2015.
    Already quite well rounded: modules, async (incl. async iteration),
    etc.
    What features are still missing?
    Details:
    My opinion
    Most important features only
    Others may also be useful (risk: bloat)
    (Mostly) based on officially proposed features

    View Slide

  3. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 3/46
    Background: How is
    Background: How is
    JavaScript designed?
    JavaScript designed?

    View Slide

  4. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 4/46
    TC39 process
    TC39 process
    TC39 (Ecma Technical Committee 39): evolves JavaScript
    Process is agile: focus is on features, not on ECMAScript releases.
    Feature proposals go through stages from 0 (strawman) to 4
    (finished).
    Yearly releases of ECMAScript versions (starting with ES2016)
    Comprise whatever features are finished

    View Slide

  5. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 5/46
    TC39 process: stages
    TC39 process: stages
    Stage 0: strawman
    Stage 1: proposal
    Stage 2: draft
    Stage 3: candidate
    Stage 4: finished
    Pick champions
    First spec text, 2 implementations
    Spec complete
    Test 262 acceptance tests
    Review at TC39 meeting
    TC39 helps
    Likely to be standardized
    Done, needs feedback from implementations
    Ready for standardization
    Sketch

    View Slide

  6. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 6/46
    Future JS: Values
    Future JS: Values

    View Slide

  7. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 7/46
    Comparing objects by value (1/2)
    Comparing objects by value (1/2)
    Comparison by value: primitives.
    Comparison by identity: objects.
    > 'abc' === 'abc'
    true
    > {x: 1, y: 4} === {x: 1, y: 4}
    false
    > ['a', 'b'] === ['a', 'b']
    false

    View Slide

  8. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 8/46
    Comparing by value (2/2)
    Comparing by value (2/2)
    Useful: comparing objects by value (“object value types”).
    Create a new kind of objects. How?
    Possibility: new object literals, new Array literals
    Possibility: new kind of class definition
    [Currently no proposal]
    > #{x: 1, y: 4} === #{x: 1, y: 4}
    true
    > #['a', 'b'] === #['a', 'b']
    true
    @[ValueType]
    class Point {
    // ···
    }

    View Slide

  9. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 9/46
    Putting objects into data structures
    Putting objects into data structures
    Solutions:
    Value types
    Customize key management via callbacks:
    Hash table: equality, hash code
    Sorted tree: comparing two keys
    const m = new Map();
    m.set({x: 1, y: 4}, 1);
    m.set({x: 1, y: 4}, 2);
    assert.equal(m.size, 2);

    View Slide

  10. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 10/46
    Large integers (1/2)
    Large integers (1/2)
    Normal numbers only give you 53 bits (plus sign) for integers:
    > 2 ** 53
    9007199254740992
    > (2 ** 53) + 1 // can’t be represented
    9007199254740992
    > (2 ** 53) + 2
    9007199254740994
    > Number.MAX_SAFE_INTEGER
    9007199254740991

    View Slide

  11. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 11/46
    Large integers (2/2)
    Large integers (2/2)
    BigInts grow as necessary:
    Fixed size (e.g. 64 bits): casting
    [ ]
    > 2n ** 53n
    9007199254740992n
    > (2n ** 53n) + 1n
    9007199254740993n
    const int64a = BigInt.asUintN(64, 12345n);
    const int64b = BigInt.asUintN(64, 67890n);
    const result = BigInt.asUintN(64, int64a * int64b);
    Stage 3 proposal

    View Slide

  12. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 12/46
    Decimal: base 10 oating point
    Decimal: base 10 oating point
    numbers (1/2)
    numbers (1/2)
    Normal numbers (base 2 floating point):
    Decimal values (base 10 floating point, stage 0):
    Important for:
    Scientific computing
    Financial technology (fintech)
    Etc.
    > 0.1 + 0.2
    0.30000000000000004
    > 0.1m + 0.2m
    0.3m

    View Slide

  13. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 13/46
    Decimal: base 10 oating point
    Decimal: base 10 oating point
    numbers (2/2)
    numbers (2/2)
    Options:
    Rationals
    Fixed-size decimals
    BigDecimals
    [ ]
    Stage 0 proposal

    View Slide

  14. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 14/46
    Categorizing values
    Categorizing values
    Problems with the status quo:
    Must decide between typeof and instanceof
    typeof quirks:
    typeof null is 'object'
    typeof a function is 'function' (not 'object')
    instanceof does not work with objects from other realms (frames
    etc.)
    May be fixable via a library (WIP of mine).

    View Slide

  15. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 15/46
    Future JS: Functional
    Future JS: Functional
    programming
    programming

    View Slide

  16. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 16/46
    More expressions (1/3)
    More expressions (1/3)
    C-style languages distinguish:
    Expressions (“produce values”):
    Statements (“do something”):
    Only expressions can be arguments in function calls, etc.
    // Conditional expression
    const str1 = someBool ? 'yes' : 'no';
    // Conditional statement
    let str2;
    if (someBool) {
    str2 = 'yes';
    } else {
    str2 = 'no';
    }

    View Slide

  17. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 17/46
    More expressions (2/3)
    More expressions (2/3)
    Proposal – do expressions:
    const str = do {
    if (someBool) {
    'yes'
    } else {
    'no'
    }
    };

    View Slide

  18. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 18/46
    More expressions (3/3)
    More expressions (3/3)
    do expression:
    [ ]
    const n = 3;
    const str = do {
    switch (n) {
    case 1:
    'one';
    break;
    case 2:
    'two';
    break;
    case 3:
    'three';
    break;
    }
    };
    assert.equal(str, 'three');
    Stage 1 proposal

    View Slide

  19. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 19/46
    Pattern matching: destructuring
    Pattern matching: destructuring
    switch
    switch
    Proposal at stage 1:
    [ ]
    const resource = await fetch(jsonService);
    case (resource) {
    when {status: 200, headers: {'Content-Length': s}} -> {
    console.log(`size is ${s}`);
    }
    when {status: 404} -> {
    console.log('JSON not found');
    }
    when {status} if (status >= 400) -> {
    throw new RequestError(res);
    }
    }
    Stage 1 proposal

    View Slide

  20. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 20/46
    Pipeline operator
    Pipeline operator
    Two competing proposals. We look at Smart Pipelines.
    Consider:
    Pipeline operator (more intuitive):
    Equivalent:
    const y = h(g(f(x)));
    const y = x |> f |> g |> h;
    f(123)
    123 |> f

    View Slide

  21. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 21/46
    Pipeline operator: partial application
    Pipeline operator: partial application
    Think .bind() – equivalent (marker #):
    Use functions as if they were methods:
    [ ]
    123 |> f('a', #, 'b')
    123 |> (x => f('a', x, 'b'))
    import {filter, map} from 'array-tools';
    const result = arr
    |> filter(#, x => x >= 0)
    |> map(#, x => x * 2)
    ;
    Stage 1 proposal

    View Slide

  22. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 22/46
    Future JS: Concurrency
    Future JS: Concurrency

    View Slide

  23. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 23/46
    Concurrency
    Concurrency
    Current de-facto standard (browsers, Node.js): Worker API
    Disadvantage: heavyweight – each Worker has its own realm (with
    global variables etc.).
    More lightweight concurrency would be nice.

    View Slide

  24. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 24/46
    Future JS: Standard library
    Future JS: Standard library

    View Slide

  25. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 25/46
    Standard library: modules instead of
    Standard library: modules instead of
    namespace objects (1/3)
    namespace objects (1/3)
    Currently – pseudo-modules:
    Math.max()
    JSON.parse()
    Object.keys()
    Reflect.ownKeys()

    View Slide

  26. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 26/46
    Standard library: modules instead of
    Standard library: modules instead of
    namespace objects (2/3)
    namespace objects (2/3)
    Wish – standard library via build-in modules (custom protocol std:):
    // New:
    import {max} from 'std:math';
    assert.equal(
    max(-1, 5), 5);
    // Old:
    assert.equal(
    Math.max(-1, 5), 5);

    View Slide

  27. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 27/46
    Standard library: modules instead of
    Standard library: modules instead of
    namespace objects (3/3)
    namespace objects (3/3)
    Benefits:
    JavaScript becomes more modular (note: also possible via “lazy”
    namespace objects):
    Possibly faster startup time
    Possibly reduced memory consumption
    Calling imported functions is faster than calling functions in
    properties
    :
    Explores first steps
    To be determined: exact functionality
    Stage 1 proposal

    View Slide

  28. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 28/46
    Standard library: helpers for iterables
    Standard library: helpers for iterables
    (sync and async) (1/3)
    (sync and async) (1/3)
    Currently: must convert iterables to Arrays.
    Better – operations that work with iterables (inspiration: Python’s
    itertools):
    const iterable = new Set([-1, 0, -2, 3]);
    const filteredArray = [...iterable].filter(x => x >= 0);
    assert.deepEqual(filteredArray, [0, 3]);
    const filteredIterable = filter(iterable, x => x >= 0);
    assert.deepEqual(
    // Only convert iterable to Array to check what’s in it
    [...filteredIterable], [0, 3]);

    View Slide

  29. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 29/46
    Standard library: helpers for iterables
    Standard library: helpers for iterables
    (sync and async) (2/3)
    (sync and async) (2/3)
    More examples:
    const iterable = new Set([-1, 0, -2, 3]);
    // Count elements in an iterable
    assert.equal(count(iterable), 4);
    // Create an iterable over a part of an existing iterable
    assert.deepEqual(
    [...slice(iterable, 2)],
    [-1, 0]);

    View Slide

  30. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 30/46
    Standard library: helpers for iterables
    Standard library: helpers for iterables
    (sync and async) (3/3)
    (sync and async) (3/3)
    More examples:
    [Currently no proposal]
    // Number the elements of an iterable
    for (const [i,x] of zip(range(0), iterable)) {
    console.log(i, x);
    }
    // Output:
    // 0, -1
    // 1, 0
    // 2, -2
    // 3, 3

    View Slide

  31. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 31/46
    Standard library: immutable data
    Standard library: immutable data
    Support for non-destructively transforming data. Existing examples:
    : lightweight; works with normal objects & Arrays.
    : more powerful and heavyweight; has its own data
    structures.
    [Currently no proposal]
    Immer
    Immutable.js

    View Slide

  32. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 32/46
    Standard library: Better support for
    Standard library: Better support for
    date times
    date times
    Stage 2 proposal: – better date time API.
    temporal
    const dateTime = new CivilDateTime(2000, 12, 31, 23, 59);
    const instantInChicago = dateTime.withZone('America/Chicago');

    View Slide

  33. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 33/46
    Features that may not be
    Features that may not be
    needed
    needed

    View Slide

  34. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 34/46
    Optional chaining: pros and cons
    Optional chaining: pros and cons
    .
    Use case:
    Equivalent:
    Stage 1 proposal
    obj?.foo?.bar?.baz
    obj?.prop
    (obj === undefined || obj === null) ? undefined : obj.prop

    View Slide

  35. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 35/46
    Optional chaining: pros and cons
    Optional chaining: pros and cons
    Pro: concise
    Cons:
    Deep nesting should be avoided (harder to change)
    Tolerance can hide problems
    Alternatives:
    Helper functions that extract data
    Pre-process (clean up) input data before working with it

    View Slide

  36. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 36/46
    Really needed: operator overloading?
    Really needed: operator overloading?
    Infix function application may be enough:
    Benefits:
    Compared to operator overloading:
    Simple mechanism
    Not limited to built-in operators
    Compared to normal function application:
    Nested expressions remain readable:
    import {BigDecimal, plus} from 'big-decimal';
    const bd1 = new BigDecimal('0.1');
    const bd2 = new BigDecimal('0.2');
    const bd3 = bd1 @plus bd2; // plus(bd1, bd2)
    a @ plus b @ minus c @ times d
    times(minus(plus(a, b), c), d)

    View Slide

  37. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 37/46
    Various smaller wishes
    Various smaller wishes

    View Slide

  38. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 38/46
    Chained exceptions
    Chained exceptions
    Indicate cause of a custom error
    new ChainedError(msg, origError)

    View Slide

  39. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 39/46
    Composable regular expressions
    Composable regular expressions
    const regex = re`/^${RE_YEAR}-${RE_MONTH}-${RE_DAY}$/u`;

    View Slide

  40. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 40/46
    Escaping text for regular expressions
    Escaping text for regular expressions
    Use case: replacing a plain text multiple times.
    > const re = new RegExp(RegExp.escape(':-)'), 'ug');
    > ':-) :-) :-)'.replace(re, ' ')
    ' '

    View Slide

  41. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 41/46
    Array.prototype.get()
    Array.prototype.get() for
    for
    negative indices
    negative indices
    > ['a', 'b'].get(-1)
    'b'

    View Slide

  42. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 42/46
    As-patterns for matching and
    As-patterns for matching and
    destructuring
    destructuring
    Proposal:
    function f(...[x, y] as args) {
    if (args.length !== 2) {
    throw new Error();
    }
    // ···
    }

    View Slide

  43. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 43/46
    Enums
    Enums
    Closing a gap with TypeScript:
    enum WeekendDay {
    Saturday, Sunday
    }
    const day = WeekendDay.Sunday;

    View Slide

  44. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 44/46
    Tagged collection literals
    Tagged collection literals
    Proposal withdrawn:
    const myMap = Map!{1: 2, three: 4, [[5]]: 6}
    // new Map([1,2], ['three',4], [[5],6])
    const mySet = Set!['a', 'b', 'c'];
    // new Set(['a', 'b', 'c'])

    View Slide

  45. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 45/46
    Take-aways
    Take-aways
    Current JavaScript is already a fairly well-rounded language.
    Main wishes:
    Value types (object that are compared by value)
    BigInts, (Big)Decimals
    Pipeline operator
    Lightweight concurrency
    Bigger standard library

    View Slide

  46. 3/11/2019 future-js.md
    http://localhost:63578/future-js.html?print-pdf#/ 46/46
    Further reading
    Further reading
    Blog post:
    My JS books (free online):
    Download slides:
    2ality.com/2019/01/future-js.html
    exploringjs.com
    speakerdeck.com/rauschma/

    View Slide