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

TC39 で提案されている ECMAScript 最新仕様 / ECMAScript latest specification proposed in TC39

森建
August 20, 2019

TC39 で提案されている ECMAScript 最新仕様 / ECMAScript latest specification proposed in TC39

森建

August 20, 2019
Tweet

More Decks by 森建

Other Decks in Programming

Transcript

  1. TC39 で提案されている
    ECMAScript 最新仕様
    pixiv Inc.
    petamoriken
    2019.8.20
    #9 FukuokaJS LT

    View Slide

  2. 2
    自己紹介
    ● 主にフロントエンドエンジニア
    ● ActionScript 3.0 を JavaScript に書き直したり
    WebGL を駆使したサイトを作ったり
    PHP のコードをリファクタリングしたり
    ● ECMAScript とか DOM API を追うのが好き
    petamoriken
    課題解決部

    View Slide

  3. 3
    Ecma International TC39 とは
    ● JavaScript の言語仕様 ECMAScript を策定する専門委員会
    ● 提案一覧は GitHub 上で管理されている
    ○ https://github.com/tc39/proposals
    ● だいたい2ヶ月おきに会議を開いている
    ○ アジェンダ: https://github.com/tc39/agendas
    ○ 議事録: https://github.com/rwaldron/tc39-notes

    View Slide

  4. 4
    ECMAScript の策定プロセス
    ● Stage 1 Proposal
    ○ 担当者が決まる
    ● Stage 2 Draft
    ○ 最初の Spec テキストが作られる
    ● Stage 3 Candidate
    ○ Spec テキストが完成し、レビューが完了する
    ● Stage 4 Finished
    ○ polyfill ではない2つの実装で互換性が確認される

    View Slide

  5. 5
    議論に参加するには
    ● 既存の提案については該当のリポジトリの issues へ
    ● 新規提案については ES Discuss というメーリングリストへ
    ○ ここ数日は Modulo Operators がホットトピック
    ○ Float16Array
    ■ polyfill 書いたら Stage 1 になった
    ○ Map#assign
    ■ 提案したらより包括的な Collection Methods が Stage 1 になった

    View Slide

  6. 具体的に各 Stage の提案を
    10個ほど紹介していきます
    6

    View Slide

  7. Stage 4 (ES2020)
    3 out of 3
    7

    View Slide

  8. 8
    String#matchAll
    ● 正規表現のキャプチャを含めてマッチした文字列を得るメソッド
    const reg = /t(e)(st(\d?))/g;
    const str = "test1test2";
    str.match(reg);
    // -> ["test1", "test2"]
    ● String#match だとキャプチャ出来ない

    View Slide

  9. 9
    String#matchAll
    ● RegExp#exec だとループ処理を書く必要がある
    let match;
    while (match = reg.exec(str)) {
    // reg.lastIndex プロパティを書き換えることで状態を保持している
    console.log(match);
    }
    // -> ["test1", "e", "st1", "1", index: 0, input: "test1test2",
    groups: undefined]
    // -> ["test2", "e", "st2", "2", index: 5, input: "test1test2",
    groups: undefined]

    View Slide

  10. 10
    String#matchAll
    ● String#matchAll を使うと安全に得られる
    for (const match of str.matchAll(reg)) {
    // Iteratorの内部で状態を保持している(RegExp#execよりも安全)
    console.log(match);
    }
    // -> ["test1", "e", "st1", "1", index: 0, input: "test1test2",
    groups: undefined]
    // -> ["test2", "e", "st2", "2", index: 5, input: "test1test2",
    groups: undefined]

    View Slide

  11. 11
    Dynamic Imports
    ● 動的にモジュールを読み込むことができるシンタックス
    ● 読み込みに成功したら以降その結果をキャッシュする
    ● 読み込み失敗時にはキャッシュされない
    ○ ちょうど一昨日その変更が入った
    Normative: change idempotency for HostImportModuleDynamically
    https://github.com/tc39/ecma262/pull/1645

    View Slide

  12. 12
    Promise.allSettled
    ● Promise が全て fullfilled か rejected のときに fullfilled する Promise を返すスタ
    ティックメソッド
    ● Promise.all は
    ○ Promise が全て fullfilled のときに fullfilled
    ○ Promise が1つでも rejected のときに rejected

    View Slide

  13. Stage 3
    3 out of 14
    13

    View Slide

  14. 14
    Weak References
    let obj = { foo: "foo" };
    const weakRef = new WeakRef(obj);
    console.log(weakRef.deref()); // -> { foo: "foo" }
    // { foo: "foo" } への参照をなくす
    obj = null;
    // しばらく経って GC によって回収されたら null になる
    console.log(weakRef.deref()); // -> null

    View Slide

  15. 15
    Weak References
    ● GC された後処理用のコールバックを登録出来る
    const finalization = new FinalizationGroup((holdings) => {
    for (const holding of holdings) {
    console.log(holding); // -> "bar"
    }
    });
    // コールバックに渡す引数とともに登録する
    finalization.register(obj, "bar");

    View Slide

  16. 16
    Weak References
    ● GC は実装によって挙動が異なるためロジックとして扱うことは非推奨
    ○ GC の順番保証はされず、タイミングを制御することは出来ない
    ○ ブラウザでタブを閉じたときに後処理用のコールバックは実行されない
    ○ 例えば GC されたら Local Storage などに退避させて、また必要になったら取り出す
    などの処理はバグる恐れがあるのでしてはいけない
    ● あくまで過剰なメモリ使用を削減したり、メモリリークを防ぐなどのために使うことを推奨して
    いる

    View Slide

  17. 17
    Nullish Coalescing Operators
    ● 主にオプションのデフォルト値周りが書きやすくなる演算子
    interface Options {
    width?: number;
    height?: number;
    duration?: number;
    }
    const options: Options = {
    width: 100,
    duration: 0,
    };

    View Slide

  18. 18
    Nullish Coalescing Operators
    ● null, undefined のときにデフォルト値を受け取るようにする
    const width = options.width != null ? options.width : 256;
    const height = options.height != null ? options.height : 256;
    const duration = options.duration != null ? options.duration : 500;
    ● Nullish Coalescing Operators で書きやすくなる
    const width = options.width ?? 256;
    const height = options.height ?? 256;
    const duration = options.duration ?? 500;

    View Slide

  19. 19
    Optional Chaining
    ● オプション自体が null の場合に対処しやすくなる
    interface Options {
    width?: number;
    height?: number;
    duration?: number;
    }
    const options: Options | null = null;

    View Slide

  20. 20
    Optional Chaining
    ● オプション自体が null の場合を考慮しないと TypeError を引き起こす
    const width = options.width ?? 256;
    // Uncaught TypeError: Cannot read property 'width' of null
    ● Optional Chaining で null, undefined に対処する
    const width = options?.width ?? 256;
    const height = options?.height ?? 256;
    const duration = options?.duration ?? 500;

    View Slide

  21. Stage 2
    3 out of 17
    21

    View Slide

  22. 22
    Decorators
    ● クラスやメソッドに @foo などを付与することで処理を追加するシンタックス
    ● 最新仕様は今年3月に登場した3代目 Built-in Decorators
    ○ TypeScript の experimentalDecorators は初代の仕様のままで全然追随出来てい
    ない
    ○ Babel は2代目の仕様のまま
    ● 詳しくは Qiita の ESNext Stage 2 Decorators の変遷と最新仕様 という記事へ

    View Slide

  23. 23
    Iterator Helpers
    ● Iterator/AsyncIterator を変換・操作するメソッド
    ● 遅延評価のため Array から Array を作るよりも無駄にならない
    ○ next メソッドで値を取り出すときに処理がなされる
    ● 詳しくは uhyo さんの JavaScriptのイテレータが持つメソッドをそろそろ知っておきたい人
    が読む記事 へ
    const iterator = [1, 2, 3, 4, 5].values();
    const array = iterator.take(3)
    .map((value) => value * 2)
    .toArray();

    View Slide

  24. 24
    Explicit Resource Managements
    ● 明示的にリソースの後処理をするシンタックス
    ● 具体的なシンタックスについてはまだ未定
    try (const fileHandle = acquireFileHandle()) {
    // スコープを抜けるときに
    // fileHandle[Symbol.dispose] が呼ばれ開放処理を行う
    }
    ● 詳しくは uhyo さんの try-using文を用いるJavaScriptの超モダンな“リソース管理” へ

    View Slide

  25. Stage 1
    1 out of 48
    25

    View Slide

  26. 26
    Emitter
    ● 今年6月に登場した期待(?)の新人
    ● Push-based Streams を扱えるインターフェースとして提案されている
    const emitter = new Emitter();
    emitter.each((value) => console.log(value)); // -> 42
    emitter.next(42);

    View Slide

  27. 27
    Emitter
    ● EventTarget から Emitter を作る
    Emitter.run(
    Emitter.on(document, "click"),
    Emitter.filter((e) => e.target.tagName === "BUTTON"),
    Emitter.map((e) => ({ x: e.clientX, y: e.clientY })),
    (coords) => console.log(coords),
    );

    View Slide

  28. 28
    Emitter
    ● Stage 1 Observable (RxJS) vs Emitter
    ○ どちらも Push-based Streams を扱える
    ○ Observable は Subscription と双方向にやりとりするが Emitter は単方向
    のみ
    ■ RxJS で言うところの Hot な状態のみを扱える
    ■ つまり Emitter は Observable よりも扱える領域は狭いと言える

    View Slide

  29. 29
    Emitter
    ● Iterable, AsyncIterable (Pull-based Streams), Promise も幅広く扱うことが出来る
    ● Emitter を経由して Iterable から Array を作る
    ○ Emitter.reduce でコレクションに変換できる
    const iterator = [1, 2, 3, 4, 5].values();
    const array = Emitter.run(
    iterator,
    Emitter.until(3),
    Emitter.map((value) => value * 2),
    Emitter.reduce([]),
    );

    View Slide

  30. 30

    View Slide

  31. 31
    Emitter
    ● まだ Stage 1 なのでよくわからないが現段階で API が結構やばめ
    ● 引数の型によって動作が変わる
    ○ Emitter.reduce(0) は number が流れてきたら足し、それ以外だと
    1足す
    ○ Emitter.reduce("") は流れてきたものを string にキャストし連結する
    ○ Emitter.reduce([]) は流れてきたものを Array#push する
    ○ Emitter.reduce({}) は流れてきたものを Object.assign する
    ● もし非同期のものが流れてきた場合はどうなるんだろう
    ……

    View Slide

  32. 32
    終わりに
    ● みなさんも TC39 の動向を追ってみてはいかがでしょうか?
    ● 個人的に Scrapbox に TC39 meeting を日本語でまとめているのでよければどうぞ

    View Slide