お正月だョ!ECMAScript Proposal全員集合!!

2019/01/08
このエントリーをはてなブックマークに追加

夢みたいな病室を担当する看護師

新年あけましておめでとうございます。カブクで主に何もしないをしているあんどうです。

いまさらで少々恥ずかしいんですが、つい先日ECMAScriptにパイプライン演算子という変態を感じる仕様が提案されていることを知り、他にどんな変態仕様が提案されているのか興味が湧いてきたので、2019年1月1日時点での全提案をざっと眺めてみました。

ECMAScriptの仕様策定プロセス

ECMAScriptの仕様策定プロセスはLiving Standardと呼ばれ、新しい仕様がオープンに提案、議論され、実装と検討が一定のステージに達したものが毎年一定のタイミングでFixされて正式な仕様として公開されます。ステージは0から4まであり、0が単なるアイデアの段階、4が正式な仕様、その間の1〜3が実際に検討が進められている提案です。

それらの提案はすべてそのステージや起案者、チャンピオンと共にGitHubリポジトリにまとめられています。今回は採用される可能性の高いステージ3から、これから正式に検討が始まる感じのステージ1までを順に紹介していきます。

ステージ3

ステージ3の提案は仕様候補で、構文やAPIなどもほぼ確定しています。また提案の仕様に準拠した実装もすでに存在します。このステージの提案は致命的な問題がなければ変更されません。

globalThis
ブラウザではwindow、ワーカーではself、nodeではglobalなど、環境により異なるグローバルオブジェクトに統一的にアクセスできるglobalThisオブジェクトを導入しようという提案
import()
現在、モジュールはimport文によって宣言的に取り込むことしかできないが、import()という関数(風の記法)によって動的に取り込めるようにしようという提案
RegExp.$1, RegExp.prototype.compile…
RegExp.$1RegExp.prototype.compileなど、ECMA 262には含まれないRegExpの古い仕様を復活させようという提案
BigInt
253-1Number.MAX_SAFE_INTEGER)よりも大きな整数を扱うためのプリミティブを導入しようという提案
import.meta
呼び出し元のスクリプト要素やモジュールのファイル名など、モジュールのメタ情報を取得できるimport.metaオブジェクトを導入しようという提案
プライベートメソッド、Getter/Setter
#というプレフィクスを使用してクラスにプライベートなメンバーを追加できるようにしようという提案。

class Counter extends HTMLElement {
  #xValue = 0;

  get #x() { return #xValue; }
  set #x(value) {
    this.#xValue = value; 
    window.requestAnimationFrame(this.#render.bind(this));
  }

  #clicked() {
    this.#x++;
  }
  ...
}
Array.prototype.flat, Array.prototyp.flatMap
ArrayオブジェクトにflatメソッドとflatMapメソッドを導入しようという提案。前者は入れ子になった配列を元に平坦な配列を返し、後者はmapの入力と結果を平坦な配列として返す。
クラスフィールド宣言
クラス定義でインスタンス変数を定義できるようにしようという提案

class Counter extends HTMLElement {
  x = 0;
}
静的メンバ
static修飾子を使用してクラスに静的メンバを追加できるようにしようという提案
String.prototype.trimStart, String.prototype.trimEnd
現在、メジャーなJSエンジンすべてでString.prototype.trimLeft/trimRightが利用できるが、非標準である。これらと同様の機能を、すでに標準として存在するpadStart/padEndと合わせてtrimStart/trimEndとして実装しようという提案
String.prototype.matchAll
正規表現マッチでグローバルオプションと部分一致を組み合わせた場合に(例:/t(e)(st(\d?))/g)、現状では部分一致を容易に得られないという問題がある。この問題に対応するためにmatchAllを導入しようという提案
Object.fromEntries
既存のObject.entriesメソッドと対になる、[key, value]の配列からObjectを構築するObject.fromEntriesを導入しようという提案
整形式のJSON.stringify
現在のJSON.stringifyは結果にUTF-8に含まれないコードポイントを含むことがあるが、これはRFC8259で規定されるJSONとしては不正である。そのような文字をエスケープシーケンスを使用して表現するようにしようという提案
Hashbang(#!)
CLIから実行する際にインタプリタを指定できるようにファイルの冒頭にShebang(例、#!/usr/bin/env node)を指定できるようにしようという提案

ステージ2

ステージ2の提案は草案です。構文やAPIなどの記述はありますが、TODOや仮の記述が残っています。また実装は実験的なものとして存在します。提案の内容は適宜変更されます。

数値セパレーター
桁数の大きな数値を読みやすくするために、数字間に_を挿入できるようにしようという提案(例、100_000_000
function.sent
ジェネレーター内でfunction.sentを使用してnextメソッドの引数にアクセスできるようにしようという提案
デコレーター
クラス定義、クラスメンバ定義にデコレーターを使用できるようにする提案。

@defineElement('num-counter')
class Counter extends HTMLElement {
  @observed #x = 0;

  @bound
  #clicked() {
    this.#x++;
  }
  ..
}
throw式
式が要求されるコンテキストでthrowを利用できるようにしようという提案。(例、function save(filename = throw new TypeError("Argument required")) { ... }
Atmics.asyncWait
アトミック演算を提供するAtmicsオブジェクトにasyncWaitを導入しようという提案
WeakRef
弱参照を実現するWeakCell/WeakRef/WeakFactoryを導入しようという提案
トップレベルawait
現状、asyncコンテキスト内でしか使用できないawaitをそれ以外の場所でも利用できるようにしようという提案
Function.prototype.toString()の抑制
Function.prototype.toString()を使用すると関数のソースコードが取得できるがこれはセキュリティ上問題がある場合がある。この問題に対応するために"use no Function.prototype.toString"というプラグマを使用することでfn.toString()の結果を[native code]にできるようにしようという提案
Setにメソッド追加
Setクラスにintersectionunionなどの集合論に基づいた各種メソッドを導入しようという提案
Realm
プログラム内で独立した環境を実現できるRealmオブジェクトを導入しようという提案
ArrayBuffer.prototype.transfer()
ArrayBufferにその所有権を移動するtransfer()メソッドを導入しようという提案
RegExp.prototype.exec()
RegExp.prototype.exec()にオプショナルな第二引数として正規表現にマッチするたびに部分文字列のインデックスを引数として呼び出されるコールバック関数を導入しようという提案
Unicodeプロパティエスケープで複数コードポイントからなる文字のサポート
正規表現で\p{...}, \P{...}という形式でUnicodeプロパティエスケープが利用できるが、これは内部的にコードポイントのリストに展開される。そのため現状では複数コードポイントからなる文字は複数の候補の集まりとして表現するしかない。この問題に対応するため複数コードポイントからなる文字用のUnicodeシーケンスプロパティエスケープを導入しようという提案
InterpreterDirective
ステージ3のHashbang(#!)と同じ提案?
Temporal
Dateオブジェクトの代替となる、よりモダンなAPIを持つCivilDate/CivilTime/CivilDateTime/Instant/ZonedInstantオブジェクトの提案

ステージ1

ステージ1はただの提案です。構文やAPIなどの詳細な記述は存在しない場合があります。また実装は単純なデモやPolyfillとして提供されます。

export v from “mod”;
インポートしたモジュールのデフォルトオブジェクトをエクスポートする構文の提案
Observable
Observable/Observerオブジェクトの提案
Frozen Realm API
Mathオブジェクトの拡張
Mathオブジェクトにclamp/scake/radians/degreesを導入しようという提案
コレクションオブジェクトのof/fromメソッド
コレクションオブジェクトを他のコレクションオブジェクトから作成する手段としてof/fromメソッドを導入しようという提案
ジェネレータアロー関数
ジェネレーターを返すアロー関数、=>*を導入しようという提案
Promise.try
Promiseでも通常の関数でも同期的に実行し、例外が発生した場合はPromise.prototype.catchで処理できるPromise.tryの提案
オプショナルチェーン
結果がnull/undefinedでなければ、その結果のプロパティにアクセスする?.記法の提案(例、user.address?.street
Math.signbit
MathオブジェクトにIEEE 754の符号ビットを返すsignbitメソッドを導入しようという提案
エラースタック
Errorオブジェクトにstackプロパティを導入しようという提案
do式
ブロックを実行してその結果を返すdo式を導入しようという提案

let x = do {
  let tmp = f();
  tmp * tmp + 1
};
Float16Array
半精度浮動小数点数を扱うFloat16Arrayを導入しようという提案
Change Number.parseInt/parseFloat to not coerce null/undefined/NaN (repo link TBD)
Number.parseInt/parseFloatnull/undefined/NaNを返さないようにしようという提案(多分)
バイナリASTフォーマット
ダウンロードサイズを小さくするためにJSのバイナリASTフォーマットを規定しようという提案
パイプライン演算子
パイプライン演算子|>を導入しようという提案

let newScore = person.score
  |> double
  |> (_ => add(7, _))
  |> (_ => boundScore(0, 100, _));
数値リテラル拡張
3_pxなどのように_を挟んで数値に単位を付けられるようにしようという提案
First-Class Protocol
mixinのようなprotocolを導入しようという提案
??演算子
||とほぼ同じだが、左辺値がnullundefinedの場合にだけ右辺値が評価される??演算子を導入しようという提案(||は左辺値が0""の場合にも右辺値が評価される)
?を使用した関数の部分適用
const addOne = add(1, ?);のように、?を使用して関数の部分適用を可能にしようという提案
Cancellation API
非同期処理のキャンセルを簡単に実現できる仕組みを導入しようという提案
String.prototype.replaceAll
文字列の一括置換を実行するString.prototype.replaceAllを導入しようという提案
String.prototype.codePoints
コードポイントのサイズは一定ではないので、codePointAtを使用して文字列のすべてのコードポイントを得るにはコードポイントの値に合わせてインクリメントする幅を切り替える必要がある。この問題に対応するため、コードポイントをイテレートするためのString.prototype.codePointsを導入しようという提案
Object.freeze/Object.seal構文
Object.freeze(例、const foo={# a:1 #};)とObject.seal(例、const foo={| a:1 |};)を簡単に実現する構文を導入しようという提案
ブロックパラメーター
Rubyのブロックパラメーターを導入しようという提案
BigInt.fromString, Number.fromString
BigInt.fromStringNumber.fromStringを導入しようという提案
Math.seededRandoms
Math.randomは乱数シードを自動的に生成するが、そうではなく、指定した乱数シードを使用するMath.seededPRNG({seed})を導入しようという提案
mixin
mixinを簡単に実現する構文を導入しようという提案。First-Class Protocolと問題領域は同じ
Array.prototype.lastItem
配列の最後の要素を取得するArray.prototype.lastItemを導入しようという提案
新しいコレクションメソッド
MapSetArrayと同じfilter/map/find...などのメソッドを導入しようという提案
オブジェクトの複合キー
Symbol.compositeKey(...values)を使用してオブジェクトのプロパティ名として複合キーを使用できるようにするという提案

const key = Symbol.compositeKey(A, B);
const o = {
  [key]:1
};
スライス記法
Pythonのようなスライス記法を導入しようという提案(例、arr[1:3]
||=, &&=
Rubyのような||=を導入しようという提案
Module Keys
モジュール間でセキュアな通信チャネルを可能にするためのAPIの提案?
Class Static Block
クラスにstaticコンテキストで実行される初期化ブロックを導入しようという提案
クラスプロパティアクセス式
class.static_member()の形式でクラスの静的メンバや無名クラスのスタティックメンバにアクセスできるようにしようという提案
パターンマッチ
次のような構文でパターンマッチを可能にしようという提案

case (res) {
  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)
  }
}
明示的なリソース管理
リソースの利用と解放を指定するusingブロックを導入しようという提案

using (const handle = acquireFileHandle()) { // リソース初期化
    ...
} // 解放
動的モジュール
ファイル単位ではなく、プログラムでモジュールを定義する手段を導入しようという提案?
標準ライブラリ
標準ライブラリを導入し、import { Date } from "std:Date";のように利用できるようにしようという提案
“use module”;
ソースコードがモジュールであることを示す"use module";プラグマを導入しようという提案
for-inの調査
for-inの仕様が曖昧な部分をいろいろと確認している?
Date.parseフォーマットの標準化
Date.parseが受け付けられる文字列のフォーマットを標準化しようという提案
JSON.parse
例えば"999999999999999999", "999999999999999999.0", "1000000000000000000"がすべて1000000000000000000と解釈されるように、JSON.parseを通すことで失われる情報がある。この問題に対応するため、JSON.parseで元の文字列を取得できるようにしようという提案
Promise.allSettled
Promiseの配列を受け取り、すべてが完了したときに結果の配列を返すPromise.allSettledを導入しようという提案
Interface Description Language (IDL)
ECMAScript標準の中で使用されているIDLの調査?
asset文
モジュールを実際には読み込まず、その利用だけを明記するasset文を導入しようという提案。実際のモジュール読込は別提案である動的importで行うことになる(例、asset Foo from "foo";

まとめ

PythonやRubyなどの他言語を参考にしたささいな便利機能の提案もそれなりに見られ※1、なんとなく思っていたほど提案のハードルは高くなさそうという印象を受けました。いま私にはかつてのようにどうでもいい言語仕様を提案してみたいという衝動がふつふつと湧いて来ています。

期待していた変態仕様についてはやはりパイプライン演算子が白眉で、それ以外は大したことがなさそうです(E4X並の変態仕様にまた出会いたい・・・)。プライベートメソッドHashbangObject.freeze/Object.seal構文などで(なんとなく)禁断の#が多用されていることからわかるように、変態文法に使用できる文字がもう余っていないのかもしれません。

ざっと提案内容全体を見ると、Javaのようなオブジェクト指向言語の方向性を伸ばしたい勢力※2と関数型言語方面の機能を追加したい勢力※3がせめぎ合いつつ前者が有力というところでしょうか。無軌道に仕様が膨らんでも誰も幸せにならないのでJavaScript Standard Libraryの提案を採用して、なんでも仕様に取り込むのではなくライブラリに切り出せるものはライブラリ側で実現されるのが個人的には理想です。とはいえ、互換性の維持を考えると実際にはその方向は難しいのかもしれません。

株式会社カブクではECMAScriptに変態文法を提案したいフロントエンドエンジニアを募集しています。


その他の記事

Other Articles

2022/06/03
拡張子に Web アプリを関連付ける File Handling API の使い方

2022/03/22
<selectmenu> タグできる子; <select> に代わるカスタマイズ可能なドロップダウンリスト

2022/03/02
Java 15 のテキストブロックを横目に C# 11 の生文字列リテラルを眺めて ECMAScript String dedent プロポーザルを想う

2021/10/13
Angularによる開発をできるだけ型安全にするためのKabukuでの取り組み

2021/09/30
さようなら、Node.js

2021/09/30
Union 型を含むオブジェクト型を代入するときに遭遇しうるTypeScript型チェックの制限について

2021/09/16
[ECMAScript] Pipe operator 論争まとめ – F# か Hack か両方か

2021/07/05
TypeScript v4.3 の機能を使って immutable ライブラリの型付けを頑張る

2021/06/25
Denoでwasmを動かすだけの話

2021/05/18
DOMMatrix: 2D / 3D 変形(アフィン変換)の行列を扱う DOM API

2021/03/29
GoのWASMがライブラリではなくアプリケーションであること

2021/03/26
Pythonプロジェクトの共通のひな形を作る

2021/03/25
インラインスタイルと Tailwind CSS と Tailwind CSS 入力補助ライブラリと Tailwind CSS in JS

2021/03/23
Serverless NEGを使ってApp Engineにカスタムドメインをワイルドカードマッピング

2021/01/07
esbuild の機能が足りないならプラグインを自作すればいいじゃない

2020/08/26
TypeScriptで関数の部分型を理解しよう

2020/06/16
[Web フロントエンド] esbuild が爆速すぎて webpack / Rollup にはもう戻れない

2020/03/19
[Web フロントエンド] Elm に心折れ Mint に癒しを求める

2020/02/28
さようなら、TypeScript enum

2020/02/14
受付のLooking Glassに加えたひと工夫

2020/01/28
カブクエンジニア開発合宿に行ってきました 2020冬

2020/01/30
Renovateで依存ライブラリをリノベーションしよう 〜 Bitbucket編 〜

2019/12/27
Cloud Tasks でも deferred ライブラリが使いたい

2019/12/25
*, ::before, ::after { flex: none; }

2019/12/21
Top-level awaitとDual Package Hazard

2019/12/20
Three.jsからWebGLまで行きて帰りし物語

2019/12/18
Three.jsに入門+手を検出してAR.jsと組み合わせてみた

2019/12/04
WebXR AR Paint その2

2019/11/06
GraphQLの入門書を翻訳しました

2019/09/20
Kabuku Connect 即時見積機能のバックエンド開発

2019/08/14
Maker Faire Tokyo 2019でARゲームを出展しました

2019/07/25
夏休みだョ!WebAssembly Proposal全員集合!!

2019/07/08
鵜呑みにしないで! —— 書籍『クリーンアーキテクチャ』所感 ≪null 篇≫

2019/07/03
W3C Workshop on Web Games参加レポート

2019/06/28
TypeScriptでObject.assign()に正しい型をつける

2019/06/25
カブクエンジニア開発合宿に行ってきました 2019夏

2019/06/21
Hola! KubeCon Europe 2019の参加レポート

2019/06/19
Clean Resume きれいな環境できれいな履歴書を作成する

2019/05/20
[Web フロントエンド] 状態更新ロジックをフレームワークから独立させる

2019/04/16
C++のenable_shared_from_thisを使う

2019/04/12
OpenAPI 3 ファーストな Web アプリケーション開発(Python で API 編)

2019/04/08
WebGLでレイマーチングを使ったCSGを実現する

2019/03/29
その1 Jetson TX2でk3s(枯山水)を動かしてみた

2019/04/02
『エンジニア採用最前線』に感化されて2週間でエンジニア主導の求人票更新フローを構築した話

2019/03/27
任意のブラウザ上でJestで書いたテストを実行する

2019/02/08
TypeScript で “radian” と “degree” を間違えないようにする

2019/02/05
Python3でGoogle Cloud ML Engineをローカルで動作する方法

2019/01/18
SIGGRAPH Asia 2018 参加レポート

2019/01/08
カブクエンジニア開発合宿に行ってきました 2018秋

2018/12/25
OpenAPI 3 ファーストな Web アプリケーション開発(環境編)

2018/12/23
いまMLKitカスタムモデル(TF Lite)は使えるのか

2018/12/21
[IoT] Docker on JetsonでMQTTを使ってCloud IoT Coreと通信する

2018/12/11
TypeScriptで実現する型安全な多言語対応(Angularを例に)

2018/12/05
GASでCompute Engineの時間に応じた自動停止/起動ツールを作成する 〜GASで簡単に好きなGoogle APIを叩く方法〜

2018/12/02
single quotes な Black を vendoring して packaging

2018/11/14
3次元データに2次元データの深層学習の技術(Inception V3, ResNet)を適用

2018/11/04
Node Knockout 2018 に参戦しました

2018/10/24
SIGGRAPH 2018参加レポート-後編(VR/AR)

2018/10/11
Angular 4アプリケーションをAngular 6に移行する

2018/10/05
SIGGRAPH 2018参加レポート-特別編(VR@50)

2018/10/03
Three.jsでVRしたい

2018/10/02
SIGGRAPH 2018参加レポート-前編

2018/09/27
ズーム可能なSVGを実装する方法の解説

2018/09/25
Kerasを用いた複数入力モデル精度向上のためのTips

2018/09/21
競技プログラミングの勉強会を開催している話

2018/09/19
Ladder Netwoksによる半教師あり学習

2018/08/10
「Maker Faire Tokyo 2018」に出展しました

2018/08/02
Kerasを用いた複数時系列データを1つの深層学習モデルで学習させる方法

2018/07/26
Apollo GraphQLでWebサービスを開発してわかったこと

2018/07/19
【深層学習】時系列データに対する1次元畳み込み層の出力を可視化

2018/07/11
きたない requirements.txt から Pipenv への移行

2018/06/26
CSS Houdiniを味見する

2018/06/25
不確実性を考慮した時系列データ予測

2018/06/20
Google Colaboratory を自分のマシンで走らせる

2018/06/18
Go言語でWebAssembly

2018/06/15
カブクエンジニア開発合宿に行ってきました 2018春

2018/06/08
2018 年の tree shaking

2018/06/07
隠れマルコフモデル 入門

2018/05/30
DASKによる探索的データ分析(EDA)

2018/05/10
TensorFlowをソースからビルドする方法とその効果

2018/04/23
EGLとOpenGLを使用するコードのビルド方法〜libGLからlibOpenGLへ

2018/04/23
技術書典4にサークル参加してきました

2018/04/13
Python で Cura をバッチ実行するためには

2018/04/04
ARCoreで3Dプリント風エフェクトを実現する〜呪文による積層造形映像制作の舞台裏〜

2018/04/02
深層学習を用いた時系列データにおける異常検知

2018/04/01
音声ユーザーインターフェースを用いた新方式積層造形装置の提案

2018/03/31
Container builderでコンテナイメージをBuildしてSlackで結果を受け取る開発スタイルが捗る

2018/03/23
ngUpgrade を使って AngularJS から Angular に移行

2018/03/14
Three.jsのパフォーマンスTips

2018/02/14
C++17の新機能を試す〜その1「3次元版hypot」

2018/01/17
時系列データにおける異常検知

2018/01/11
異常検知の基礎

2018/01/09
three.ar.jsを使ったスマホAR入門

2017/12/17
Python OpenAPIライブラリ bravado-core の発展的な使い方

2017/12/15
WebAssembly(wat)を手書きする

2017/12/14
AngularJS を Angular に移行: ng-annotate 相当の機能を TypeScrpt ファイルに適用

2017/12/08
Android Thingsで4足ロボットを作る ~ Android ThingsとPCA9685でサーボ制御)

2017/12/06
Raspberry PIとDialogflow & Google Cloud Platformを利用した、3Dプリンターボット(仮)の開発 (概要編)

2017/11/20
カブクエンジニア開発合宿に行ってきました 2017秋

2017/10/19
Android Thingsを使って3Dプリント戦車を作ろう ① ハードウェア準備編

2017/10/13
第2回 魁!! GPUクラスタ on GKE ~PodからGPUを使う編~

2017/10/05
第1回 魁!! GPUクラスタ on GKE ~GPUクラスタ構築編~

2017/09/13
「Maker Faire Tokyo 2017」に出展しました。

2017/09/11
PyConJP2017に参加しました

2017/09/08
bravado-coreによるOpenAPIを利用したPythonアプリケーション開発

2017/08/23
OpenAPIのご紹介

2017/08/18
EuroPython2017で2名登壇しました。

2017/07/26
3DプリンターでLチカ

2017/07/03
Three.js r86で何が変わったのか

2017/06/21
3次元データへの深層学習の適用

2017/06/01
カブクエンジニア開発合宿に行ってきました 2017春

2017/05/08
Three.js r85で何が変わったのか

2017/04/10
GCPのGPUインスタンスでレンダリングを高速化

2017/02/07
Three.js r84で何が変わったのか

2017/01/27
Google App EngineのFlexible EnvironmentにTmpfsを導入する

2016/12/21
Three.js r83で何が変わったのか

2016/12/02
Three.jsでのクリッピング平面の利用

2016/11/08
Three.js r82で何が変わったのか

2016/12/17
SIGGRAPH 2016 レポート

2016/11/02
カブクエンジニア開発合宿に行ってきました 2016秋

2016/10/28
PyConJP2016 行きました

2016/10/17
EuroPython2016で登壇しました

2016/10/13
Angular 2.0.0ファイナルへのアップグレード

2016/10/04
Three.js r81で何が変わったのか

2016/09/14
カブクのエンジニアインターンシッププログラムについての詩

2016/09/05
カブクのエンジニアインターンとして3ヶ月でやった事 〜高橋知成の場合〜

2016/08/30
Three.js r80で何が変わったのか

2016/07/15
Three.js r79で何が変わったのか

2016/06/02
Vulkanを試してみた

2016/05/20
MakerGoの作り方

2016/05/08
TensorFlow on DockerでGPUを使えるようにする方法

2016/04/27
Blenderの3DデータをMinecraftに送りこむ

2016/04/20
Tensorflowを使ったDeep LearningにおけるGPU性能調査

→
←

関連職種

Recruit

→
←

お客様のご要望に「Kabuku」はお応えいたします。
ぜひお気軽にご相談ください。

お電話でも受け付けております
03-6380-2750
営業時間:09:30~18:00
※土日祝は除く