JavaScript の標準仕様 ES2020 (ECMAScript 11th Edision) として 2020年6月にリリースされました。ES2020 で新たに追加された機能について説明していきます。
これまでの JavaScript では、2^53 の精度の整数しか扱うことができませんでしたが、任意の精度を持つ整数 BigInt がサポートされました。数字を BigInt 整数として表現するには数字の末尾に n をつけます。
var num1 = 123n;
通常の整数では17桁あたりから丸め誤差が出始めますが、BigInt 整数は何桁であっても誤差が生じることはありません。
console.log(1234567890123456789); // => 1234567890123456800 ... 末尾に誤差が出ることがある console.log(1234567890123456789n); // => 1234567890123456789n ... 誤差は生じない
通常の整数を BigInt 整数に変換するには BigInt() を用います。
var num1 = 123; // 通常精度の整数 var num2 = BigInt(num1); // BigInt整数
typeof の値は bigint となります。
console.log(typeof(123n)); // => bigint
オブジェクトの属性等を for-in ループで参照する際、これまでは順序が保障されませんでしたが、ES2020 では順序が保障されるようになりました。下記の例では、処理系によっては順不同で表示される可能性がありましたが、ES2020 では a, b, c, d, e の順に表示されることが保障されます。
var data = {a:"A", b:"B", c:"C", d:"D", e:"E"};
for (var d in data) {
console.log(d); // => a, b, c, d, e
}
ヌル合体(Nullish Coalescing)演算子 ?? を用いることで、値が undefined や null の時にデフォルト値を設定するといった処理を、下記の様に記述することが可能となります。
// 古い書き方(obj.fooが未設定の場合デフォルト値60を設定する) if (typeof(obj.foo) == "undefined" || obj.foo == null) { obj.foo = 60; } // ES2020以降の新しい書き方 obj.foo = obj.foo ?? 60;
これまで、obj.foo.baa などの参照で、foo が未定義の場合 TypeError が発生していましたが、オプショナル連結 ? を用いることで、foo が未定義の場合は TypeError ではなく undefined を返却させることが可能となりました。
// 古い書き方(obj.fooが定義されていたら参照する) if (obj.foo) { console.log(obj.foo.baa); } // ES2020以降の新しい書き方 console.log(obj.foo?.baa); // => foo が未定義の場合は undefined
ブラウザで動作する JavaScript でも、サーバ上で動作する Node.js でも共通に参照できるグローバルオブジェクトとして globalThis がサポートされました。ブラウザで動作する JavaScript では window オブジェクト、Node.js では global オブジェクトと同値になります。
console.log(globalThis); // => Window {window:...}
string.matchAll(regexp) は、string の中から regexp にマッチするものをリスト(正確にはイテレーター)として返却します。
for (var m of "2020-12-31".matchAll(/[0-9]+/g)) { console.log(m); } // => ["2020", index: 0, input: "2020-12-31", groups: undefined] // => ["12", index: 5, input: "2020-12-31", groups: undefined] // => ["31", index: 8, input: "2020-12-31", groups: undefined]
モジュールを非同期に読み込むことが可能となりました。import() は Promise を返却します。非同期にモジュールを読み込み、読み込みが完了した時点でコールバック関数を実行することができます。
import("./module.js").then(mod => { console.log(mod.a1); });
インポートしたものを直接エクスポートすることが可能となりました。
// 以前の古い書き方 import * as mod from "./module.js"; export { mod }; // ES2020以降の新しい書き方 export * as mod from "./module.js";
import.meta がサポートされました。現在のモジュールに関する URL などのメタ情報を得ることができます。
console.log(import.meta);
// => {url, "http://www.example.com/example.js"}
Promise.all() では、指定したタスクのいずれか一つがエラーになるとそこで待ち合わせを完了してしまいますが、新しくサポートされた Promise.allSettled() を用いると、タスクがエラーとなっても、すべてのタスクが成功終了するか、エラー終了するまで、処理を待ち合わせることが可能となります。
p1 = Promise.resolve("OK1"); p2 = Promise.reject("NG2"); p3 = Promise.resolve("OK3"); Promise.allSettled([p1, p2, p3]).then( resolveList => resolveList.forEach(res => console.log(res)), rejectList => rejectList.forEach(rej => console.log(rej)) ); // => {status: "fulfilled", value: "OK1"} // => {status: "rejected", reason: "NG2"} // => {status: "fulfilled", value: "OK3"}