ECMAScriptの最新動向 2022年03月版
Published on
この記事では2022年03月28日~31日に開催された TC39 meeting 89th で議題に上がったプロポーザルを紹介します。
For Stage 4
For Stage 4 の提案はありませんでした。
For Stage 3
RegExp set notation + Unicode properties of strings
Stage 3 に到達しました
このプロポーザルは正規表現に新しくv
フラグを導入し、その中で set notation と Unicode properties of strings を使えるようにします。
(翻訳するとしたら set notation は「集合の表記」、properties of strings は「文字列プロパティ」でしょうか。定訳がわからないのでこの記事ではこれらの用語を英語のまま表記します。)
まず、set notation とは次のような記法のことです。
(A
や B
は character class ([a-z]
など) もしくは Unicode property escape (\p{ASCII}
など) とします)
// 差(difference/subtraction)
[A--B]
// 共通部分(intersection)
[A&&B]
// nested character class
[A--[0-9]]
プロポーザルのリポジトリでは実用的なユースケースが紹介されています。
次に Unicode properties of strings は、domain が character や code point ではなく string (character の sequence) であるような Unicode property のことです。 (Unicode の property については Unicode の UTS18 の Properties を読むのがわかりやすいと思います)
このプロポーザルの中では次の property of string がサポートされるようです。(ref: https://github.com/tc39/ecma262/pull/2418/files#diff-00f81a4e81713d00d0ebd710c18a798b699d244361ceb04fecbb06db6b32e8ba)
(見たところどれも Binary のものしかありませんが、今後他の datatype のものも追加されるかどうかはわかりません)
Basic_Emoji
Emoji_Keycap_Sequence
RGI_Emoji_Modifier_Sequence
RGI_Emoji_Flag_Sequence
RGI_Emoji_Tag_Sequence
RGI_Emoji_ZWJ_Sequence
RGI_Emoji
これによって複数の code point からなる Emoji に対して Unicode property escape を使ってマッチさせられるようです。
(Unicode についてはあまり詳しくないので記述について誤りを見つけた人は教えてほしいです。)
ちなみに Unicode properties of strings はもともとは別のプロポーザルでしたが、2021年5月にこのプロポーザルにマージされました。
Change Array by Copy
Stage 3 に到達しました
Change Array by Copy は Array と TypedArray にいくつかのイミュータブルなメソッドを追加するプロポーザルです。
以前この提案について記事を書いたのでより深く知りたい場合はそちらも参照してください(この記事は約1年前に書かれたものなので、現在提案されている仕様とは異なる部分があります)。
このプロポーザルについての議論では、新たに追加されるメソッドをどのように命名するかが主な論点にあがっていました。
現在では次のような with
+ メソッド名の過去形(過去分詞形?)
という形で落ち着いたようです。
// ミュータブルなメソッド
["a", "b", "c"].reverse();
// イミュータブルなメソッド
["a", "b", "c"].withReversed();
これらのメソッドは便利な一方、配列をコピーして返すため配列の要素数に応じて発生するオーバーヘッドを考慮して使う必要があります。
Decorators
Stage 3 に到達しました
Decorators はクラスを拡張するための構文を導入するプロポーザルです。
このプロポーザルは5年以上に渡って議論が行われてきた上、TypeScript によって早期からサポートされていたため開発者に広く認知されています。
ミーティングで使われたスライドの冒頭では
What is a decorator? Decorators are functions which have four main capabilities when applied to a class or class element
- Replacement
- Initialization
- Metadata
- Access
と説明されています。
ちなみに現在 TypeScript に実装されている Decorators は現在の TC39 の Decorators とは異なるものです。TypeScript 4.8 で TC39 の Decorators を実装することが検討されています。
筆者としては、Decorators はコードを書くときの体験を大きく変えうる機能である一方で、複雑で厄介なコードを生み出す可能性も高い機能だと考えています。 したがって一般的な Web アプリケーション開発にとっては、ライブラリが提供する Decorators を使用する程度にとどめておくのが、適切な関わり方なのではないかと思っています。
この新しい Decorators に対してコミュニティがどのように向き合っていくのか、動向が気になるところです。
For Stage 2
Pattern Matcing
Stage 2 に到達しませんでした
Pattern Matching は名前の通りパターンマッチを導入するためのプロポーザルです。
現在の ECMAScript では正規表現を除き値のマッチングを行うことができません。
また、switch
文にはよく知られたいくつかの問題があります。
- 式として使えない
- 各
case
に明示的なbreak
で必要である - 各
case
でスコープが曖昧である - など
Pattern Matching ではこれらの問題に対処するための新しい構文を導入します。
例を示します。
match (res) {
when ({ status: 200, body, ...rest }): handleData(body, rest)
when ({ status, destination: url }) if (300 <= status && status < 400):
handleRedirect(url)
when ({ status: 500 }) if (!this.hasRetried): do {
retry(req);
this.hasRetried = true;
}
default: throwSomething();
}
match
からはじまるブロック全体は match construct と呼ばれます。match construct 全体で一つの式として振る舞います。match(res)
のres
は matchable と呼ばれます。matchable は任意の式です。when
やdefault
で始まる部分を clause (句) と呼びます。clause は:
で LHS と RHS に区切られます。- clause の LHS は
when
もしくはdefault
で始まる必要があります。when
clause は、when
というキーワードのあとにカッコで囲まれた pattern を記述します。- カッコで囲まれた pattern のあとには
if
と条件式で構成された guard を記述することができます。pattern の表現力では不十分だった場合に guard を使ってさらなるロジックを記述できます。
- カッコで囲まれた pattern のあとには
default
clause は他のどの clause にもマッチしなかった場合にマッチします。default
clause はなくても問題ありませんが、使う場合はからなず最後に置かなければいけません。
- clause の RHS は任意の式です。ブロックステートメント(
{ }
)を書くことはできません。なので、複雑なロジックを記述したいときは現在では即時実行関数を使う必要があります。将来的には、現在提案されている do expression がここで役に立つでしょう。
- clause の LHS は
when
clause に続く pattern では、実際にはもっと複雑なパターンを記述できます。(ref: https://github.com/tc39/proposal-pattern-matching#pattern)
Pattern Mathcing は JavaScript のコーディングスタイルを大きく変えうる強力な機能です。
今回のミーティングでは仕様のテキストに懸念があり、時間内に Stage 2 に到達する合意は得られなかったようです。
For Stage 1
Function.prototype.once
Stage 1 に到達しました
Function.prototype.once
は、Function
に一度だけ呼び出されるような関数を作るためのインスタンスメソッドを導入するプロポーザルです。
例を示します。関数 f
は受け取った引数を出力し、それに2をかけた数を返す関数です。
このとき f.once()
は、一度だけ f
を呼び出す関数を返します。f.once()
の返り値の関数を二度以上呼び出しても f
が再度呼び出されることはなく、その返り値は最初のf
の返り値となります。
function f (x) { console.log(x); return x * 2; }
const fOnce = f.once();
fOnce(3); // `3` が出力され、`6` が返される
fOnce(3); // 何も出力されず、`6` が返される
fOnce(2); // 何も出力されず、`6` が返される
プロポーザルのリポジトリでは実用的なユースケースが紹介されています。
Type Annotations
Stage 1 に到達しました
Type Annotations プロポーザルは、ECMAScript の仕様に TypeScript や Flow のような型の構文を導入するプロポーザルです。
たとえば、次に示すような型注釈を含むコードが JavaScript のプログラムとして妥当になります。
const foo: string = "foo";
function bar(param: number) {
return param.isNaN();
}
このプロポーザルでは ECMAScript に型チェックを導入するのではなく、あくまで型の構文だけを導入します。つまり型による静的チェックを行う場合はこれまで通り統合開発環境やTypeScript Compilerなどを使う必要があります。
このプロポーザルについて以前記事を書いたので興味のある人はそちらも参照してください。
また、過去に Harajuku.ts という勉強会で @uhyo_ さんと @okunokentaro さんと議論したので興味のある人はそのときのアーカイブも御覧ください。
Updates
ステージの移動はないものの更新が紹介された提案を列挙します。ここでは詳細については説明しませんがスライドや関連するIssueへのリンクを貼ったので興味のある人は参照してください。
Array Grouping
Resizable Array Buffer
Temporal
Shadow Realms
Pipe Operator
Call-this operator
String.dedent
参考リンク
- TC39
- Babel
- TypeScript
- Unicode
記事に関する報告などはこちらから