ECMAScript proposal updates @ 2020-07 の簡単な要約


これは何

ECMAScript proposal updates @ 2020-07 | ECMAScript Daily の簡単な要約です。次の JavaScript バージョンに加わる可能性のある新文法、新メソッド、新クラスがまとめられています。

正確・詳細な内容を知りたい方はリンク先をあたってください。そこまでするほどではないけどざっくり知りたい、という方向けです。

New Proposals

Proposal Stage
Import Conditions 2
WeakRefs cleanupSome 2
JSON Modules - Note 2
await operations 1
Array.prototype.unique() 1
ResizableArrayBuffer and GrowableSharedArrayBuffer 1

Updated Proposals

Proposal From To
Promise.any 3 4
WeakRefs 3 4
Logical Assignment Operators 3 4
Numeric separators 3 4
.item() 1 2
Record & Tuple 1 2
JSON.parse source text access 1 2

New Proposals

Import Conditions

JSON modules の import にアサーションが書けるようになります。

import json from "./foo.json" assert { type: "json" };

foo.json が実際は JSON ではなかったときに、意図しないスクリプトを実行してしまうセキュリティ問題を防ぐためのようです。ファイルタイプを表すため慣例的に拡張子が使われているものの、本来 Web は拡張子という概念のない世界だから MIME Type とのミスマッチを明示的にすべき、らしいです。

アプリコードを書くときには煩わしいので、Babel や TypeScript による自動付与、VS Code による補完がどうなるか気になります。

WeakRefs cleanupSome

WeakRefs がわかっていないのでわからない

ガベージコレクションの話なので、よほど性能チューニングしたいときにしか使わなそう。

JSON Modules - Note

Import のアサーションと JSON modules の話は分けるべきでは?という議論。結論までちゃんと読んでないです。

await operations

Promise.all() などが書きやすくなります。

// before
await Promise.all(users.map(async x => fetchProfile(x.id)));

// after
await.all users.map(async x => fetchProfile(x.id));

all のほか race, allSettled, any も。

Array.prototype.unique()

配列の重複を除くメソッドが使えるようになります。

const data = [
  { id: 1, uid: 10000 },
  { id: 2, uid: 10000 },
  { id: 3, uid: 10001 },
];

data.unique("uid");
// [
//   { id: 2, uid: 10000 },
//   { id: 3, uid: 10001 }
// ]

data.unique(({ id, uid }) => `${id}-${uid}`);
// [
//   { id: 1, uid: 10000 },
//   { id: 2, uid: 10000 },
//   { id: 3, uid: 10001 }
// ]

現時点でも [...new Set(array)] によって配列の重複は除けますが、プリミティブ型でない値には使えません。その点を補います。

一方で、Record & Tuple によってオブジェクト的な値の同値性チェックが簡単になれば、プリミティブ型でない値にも使えるというメリットは薄まりそうです。メソッド名がわかりやすいので追加されること自体はよいことです。

ResizableArrayBuffer and GrowableSharedArrayBuffer

ArrayBuffer の派生クラスが増えます。

let rab = new ResizableArrayBuffer(1024, 1024 ** 2);
rab.resize(1024 * 2);

既存の ArrayBuffer は、領域を拡大するにはバッファーコピーが必要で非効率的だし、32-bit システムではアドレス空間のフラグメント化が生じるから、サイズ可変なこれらが欲しいとのこと。

あまり ArrayBuffer を使わないのでわかりませんが、動画のような巨大なバイナリ処理が効率化できるということでしょうか。

Updated Proposals

Promise.any

複数の promise のうちの一つが解決するまで待つ promise を作れます。

try {
  const first = await Promise.any(promises);
  // Any of the promises was fulfilled.
} catch (error) {
  // All of the promises were rejected.
}

Promise.race([a, b, c])a, b, c のどれか一つが 解決 or 拒否(失敗) すると解決 or 拒否します。Promise.any([a, b, c])a, c が拒否しても b解決 するまで待って、b が解決したら解決、全部拒否したら拒否になります。

3 社の広告(接続先すべて別)のうちどれか一つを表示できればよい、といったケースで役に立ちそう?

WeakRefs

わからない

ガベージコレクション (GC) の話なので、よほど性能チューニングしたいときにしか使わなそう。iOS アプリなどと違って Web はページ単位のライフサイクルで、GC タイミングが多いはず(感覚です)。とはいえ Web の高機能化に伴って、明示的なメモリー管理も必要になるかもしれません。

Logical Assignment Operators

論理演算子も代入書式が使えるようになります。

opts.baz ??= "qux";

// eq
opts.baz ?? (opts.baz = "qux");

i = i + 1i += 1 と書くようなものです。デフォルトオプションを設定するのに役立ちそう。||=, &&=, ??= の 3 種類あります。

TypeScript 4.0 Beta ですでに導入されているようです (https://devblogs.microsoft.com/typescript/announcing-typescript-4-0-beta/)

Numeric separators

数値の桁をアンダースコア _ で区切れるようになります。

101_475_938.38 === 101475938.38;

すでにこう書けます(Chrome 84 や Node 13)が、仕様として定まっていないところがあったということでしょうか。ちゃんと読んでいないです。

.item()

N 番目の要素を取得するとき、負の値を指定できるようになります。

["a", "b", "c"].item(-1) === "c";

Array, String, TypedArray にメソッドが追加されます。[] を使わないのは、それが配列インデックスだけでなくオブジェクトのプロパティを指定するときにも使われるためです。arr[-1] という書き方は現状可能ですが、arr["-1"] と書いたことになってしまいます。それらの区別をつけるため、明示的にメソッドを追加するようです。

Record & Tuple

イミュータブルな構造体として Record と Tuple が使えるようになります。

// Record
const doc = #{
  id: 123,
  title: "foo",
};

doc.title === "foo";

// Tuple
const m = #["x", "y", "z"];

m[1] === "y";

Record はオブジェクトのような構造体、Tuple は配列のような構造体です。TypeScript はすでに as const キーワードによってイミュータブルな構造体を表せますが、JS としても同様のことが可能になります。

一方 TypeScript でも実現できていない点として、同値性の評価があります。イミュータブルなので、中の構成が一緒なら同値であると評価するようです。

// non-Record
assert({ x: 1, y: 2 } !== { x: 1, y: 2 });

// Record
assert(#{ x: 1, y: 2 } === #{ x: 1, y: 2 });

プリミティブ型のようにイミュータブルかつ比較も簡単な値に、オブジェクトと同じ情報量を持たせられるのは強力です。

JSON.parse source text access

JSON.parse のパーサーロジックを拡張できるようになります。

ちゃんと読んでいないです。