v4.0.0: ES2022
jsprimer.net がECMAScript 2022(ES2022)に対応しました。
ES2022への対応して、次の内容が更新されています。
また、ウェブ版の仕組みとしてユースケースの章などのHTMLを使ったアプリケーションもウェブ上でそのまま変更しながら確認できるエディタを組み込んでいます。
Top-Level await
ES2021までは、await
式はAsync Functionの直下でのみしか利用できませんでした。
ES2022には、これに加えてModuleの直下では、Async Functionで囲まなくてもawait
式が利用できます。
console.log("start");
// awaitを使って1秒待つ
await new Promise(resolve => setTimeout(resolve, 1000));
console.log("end");
これにより、await
式を使うためだけにAsync Functionを使った即時実行関数は不要となります。
// awaitを使うためだけに、Async Functionの即時実行関数を実行している
(async function() {
// awaitを使う処理
const result = await doAsyncTask();
// ...
})();
Object.hasOwn
ES2022ではObject.hasOwn
静的メソッドが追加されました。
Object.hasOwn
静的メソッドは、対象のオブジェクトが指定したプロパティを持っているかを確認できるメソッドです。
const obj = { key: "value" };
// `obj`が`key`プロパティを持っているならtrueとなる
if (Object.hasOwn(obj, "key")) {
console.log("`obj`は`key`プロパティを持っている");
}
このObject.hasOwn
静的メソッドは、Object.prototype.hasOwnProperty
メソッドを置き換える目的で導入されています。
hasOwnProperty
メソッドは、Object.create(null)
で作成したような"prototypeを継承していないオブジェクト"からは直接呼び出せないという欠点があります。
// prototypeを継承していないオブジェクト
const obj = Object.create(null);
// `Object.prototype`を継承していないため呼び出すと例外が発生する
console.log(obj.hasOwnProperty("key")); // => Error: hasOwnPropertyメソッドは呼び出せない
Object.hasOwn
静的メソッドは、インスタンスオブジェクトではなく静的メソッドであるため、対象のオブジェクトに関係なく利用できます。
// prototypeを継承していないオブジェクト
const mapLike = Object.create(null);
// keyは存在しない
console.log(Object.hasOwn(mapLike, "key")); // => false
Array.prototype.at
配列の末尾の要素へアクセスするには、array[array.length - 1]
というlength
プロパティを使う必要がありました。
array
を2回書く必要があるなど、末尾の要素へのアクセスは少し手間が必要になっていました。
この問題を解決するためES2022では、相対的なインデックスの値を指定して配列の要素へアクセスできるArray.prototype.at
メソッドが追加されました。
Arrayのat
メソッドは、配列[インデックス]
とよく似ていますが、引数には相対的なインデックスの値を引数として渡せます。.at(0)
なら配列の先頭の要素へ、.at(-1)
なら配列の末尾の要素へアクセスできます。
const array = ["a", "b", "c"];
// 先頭の要素にアクセス
console.log(array.at(0)); // => "a"
console.log(array[0]); // => "a"
// 後ろから1つ目の要素にアクセス
console.log(array.at(-1)); // => "c"
console.log(array[array.length - 1]); // => "c"
String.prototype.at
配列と同じく文字列にも相対的なインデックスの値を指定して文字へアクセスできるString.prototype.at
が追加されました。
const str = "文字列";
console.log(str.at(0)); // => "文"
console.log(str.at(1)); // => "字"
console.log(str.at(2)); // => "列"
console.log(str.at(-1)); // => "列"
Public/Privateクラスフィールド
ES2022ではクラスにクラスフィールド構文が追加されました。
クラスフィールドは、PublicクラスフィールドとPrivateクラスフィールドの2種類があります。
Publicクラスフィールドは、次のようにクラスのインスタンスに対するプロパティを宣言的に定義できる構文です。
class Counter {
count = 0;
increment() {
this.count++;
}
}
const counter = new Counter();
counter.increment();
console.log(counter.count); // => 1
一方のPrivateクラスフィールドは、フィールド名の前に#
をつけることで、クラスの外からはアクセスできないプライベートなプロパティを定義できる構文です。
class NumberWrapper {
// valueはPrivateクラスフィールドとして定義
#value;
constructor(value) {
this.#value = value;
}
// `#value`フィールドの値を返すgetter
get value() {
return this.#value;
}
// `#value`フィールドに値を代入するsetter
set value(newValue) {
this.#value = newValue;
}
}
const numberWrapper = new NumberWrapper(1);
console.log(numberWrapper.value); // => 1
// クラスの外からPrivateクラスフィールドには直接はアクセスできない
// console.log(numberWrapper.#value); // => SyntaxError: reference to undeclared private field or method #value
今までは、クラスのインスタンスにプロパティを定義するにはクラスのconstructor
メソッド内で値を代入する必要がありました。クラスフィールドでは、インスタンスへのプロパティの定義をより宣言的に行えます。
また、Privateクラスフィールドでは #
という新しい記号を利用します。
そのため、今までprototypeの省略記号として #
を利用していた部分は全て書き換えています。
その他
そのほかにもES2022ではRegular expression match indices、スタックトレースを継承するError cause、 static blocksなどが追加されています。
ウェブエディタの改善
jsprimer.net のウェブ版では、JavaScriptのコードをそのままブラウザで実行できるコンソール機能が実装されています。
今までは、JavaScript実行のみしか扱えませんでしたが、そのため表示を扱うユースケースであるTodoアプリなどはローカルサーバを使って確認する必要がありました。
今回、jsprimerにHTMLの表示も伴うコードにも対応したエディタを組み込みました。
CodeSandboxが提供しているComponent toolkit for creating live-running code editing experiences | Sandpackを使いエディタを組み込んでいます。
エディタの右下のボタンから、CodeSandboxで開いてコードを共有も可能です。
最初にjsprimerでは、書籍をよりよくしていくための改善案などは常に募集しています。
また、今回のアップデートに関連して特に意見を募集している箇所はDiscussionのスレッドを作成しているので、興味がある人はコメントしてくダサい。