JavaScript Primer(jsprimer.net)が、ECMAScript 2022(ES2022)に対応しました。

これまでのjsprimer

ECMAScriptの仕様書は毎年更新されるので、それに合わせてjsprimerも更新しています。

今回のアップデートでは、2022-6-22にリリースされたES2022に対応した変更をしています。

今後GitHubで更新情報を購読したい人は、asciidwango/js-primerリポジトリを“Watch”してください。 “Custom”からリリースのみを購読も可能です。

GitHub Watchesの登録画面

更新通知をメールで受け取り方は、次のフォームからメールアドレスを登録してください。

JavaScript Primerの更新情報を購読

* indicates required

フォームが表示されない人は http://eepurl.com/gZOIgb から登録できます。

今回のアップデートのような大きめな更新情報をメールで受け取れます。

書籍への支援について

継続的にアップデートするために、書籍への支援はいつでも歓迎しています。 JavaScript PrimerはECMAScriptのアップデートに追従したり、現実の使い方を反映するために、継続してアップデートしています。

GitHub Sponsorsで著者を支援できます。

また、書籍版へのレビューを書くことも支援に繋がります。

GitHubのDiscussions(掲示板)の他の人の質問に答えたり、ブログにjsprimerを読んだ感想を書くことも支援になります。

Discussionsのガイドラインは次のスレッドにまとめられています。

書籍に対してIssueを立てたり、Pull Requestを送ったりして直接的に支援もできます。 IssueやPull Requestについては、次のページを参照してください。

jsprimerの今後について

まだ詳細は未決定ですが、書籍版の改訂を進めていくための作業をしていく予定です。

書籍版の初版はES2019相当がベースにしたスナップショットとなっています。 現在のウェブ版はES2020/ES2021/ES2022の対応で内容を変更したり追加しているため、あらためて全体を見て読みやすく調整していく作業をしていく予定です。

特にクラス非同期処理は、もともと内容が難しいのに加えて長くなってしまってるので、これを読みやすくするアイデアとか意見を募集しています。

それぞれDiscussionのスレを作ってあるので、こうだったら分かりやすくなりそうとか、ここら辺がわかりにくかったとかの意見やアイデアがあったらコメントください。

また、次の改訂に向けて内容がある程度整理できてきたら、あらためて全体をレビューしてもらえる人を募集しています。 もし、レビューできるよって方がいたら、Twitterか次のDiscussionにコメントください。 依頼するタイミングになったらあらためてお知らせします。

前回レビューしていただいた方は、書面にも掲載させていただいています。

JavaScript Primer 4.0.0の変更点

jsprimer.net 4.0.0の変更点の紹介です。

ES2022への対応して、次の内容が更新されています。 また、ウェブ版の仕組みとしてユースケースの章などのHTMLを使ったアプリケーションもウェブ上でそのまま変更しながら確認できるエディタを組み込んでいます。

Top-Level await

https://jsprimer.net/basic/async/#top-level-await-in-module

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

https://jsprimer.net/basic/object/

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

https://jsprimer.net/basic/array/

配列の末尾の要素へアクセスするには、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

https://jsprimer.net/basic/string/

配列と同じく文字列にも相対的なインデックスの値を指定して文字へアクセスできる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メソッド内で値を代入する必要がありました。クラスフィールドでは、インスタンスへのプロパティの定義をより宣言的に行えます。

その他

そのほかにもES2022ではRegular expression match indices、スタックトレースを継承するError cause、 static blocksなどが追加されています。

ウェブエディタの改善

jsprimer.net のウェブ版では、JavaScriptのコードをそのままブラウザで実行できるコンソール機能が実装されています。

今までは、JavaScript実行のみしか扱えませんでした。 そのためHTMLといった表示を扱うユースケースであるTodoアプリなどはローカルサーバを使って確認する必要がありました。 今回、jsprimerにHTMLの表示も対応したエディタを組み込みました。

Sandpack on jsprimer

CodeSandboxが提供しているComponent toolkit for creating live-running code editing experiences | Sandpackを使いエディタを組み込んでいます。 エディタの右下のボタンから、CodeSandboxで開いてコードを共有も可能です。

これからjsprimer読む方へ

JavaScript Primer - 迷わないための入門書 #jsprimerをまだ読んだことなくて、これから読みたい方へ。

書籍版の内容はウェブ版と基本的に同じですが、本として読めるように内容とレイアウトが最適化されています。 また、書籍版はある時点(ES2019)のスナップショットで、ウェブ版は常にアップデートされています。

書籍版は細かく校正を行った後にレイアウトを組んで作っているため、読み物としては書籍版の方が読みやすくなっています。 一方のウェブ版は、最新(ES2022)の仕様を含めた変更を取り入れています。 また、ウェブ版では検索機能やサンプルコードを実行できる機能が組み込まれているため、必要に応じて併用してください。

詳細は次のページでも書いています。

jsprimerをちょっとづつ読んでいきたい方向けに、チェックリストも用意してあります。 章ごとにチェックして進められるので、章ごとにわからなかった部分をメモしたりして自分のペースで進めるための補助的なツールとして使ってください。