Pro Yearly is on sale from $80 to $50! »

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.

5592487d2231fbe06ed2ac80d92c8f20?s=128

Axel Rauschmayer

March 11, 2019
Tweet

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
  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
  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?
  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
  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
  6. 3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 6/46 Future JS: Values Future JS: Values

  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
  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 { // ··· }
  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);
  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
  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
  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
  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
  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).
  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
  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'; }
  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' } };
  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
  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
  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
  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
  22. 3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 22/46 Future JS: Concurrency Future JS: Concurrency

  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.
  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
  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()
  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);
  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
  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]);
  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]);
  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
  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
  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');
  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
  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
  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
  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)
  37. 3/11/2019 future-js.md http://localhost:63578/future-js.html?print-pdf#/ 37/46 Various smaller wishes Various smaller wishes

  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)
  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`;
  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, ' ') ' '
  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'
  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(); } // ··· }
  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;
  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'])
  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
  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/