ECMAScript 2020の変更に対応したJavaScriptの入門書としてJavaScript Primer 2.0.0を公開しました。

JavaScript Primerのウェブサイトから閲覧できます。

変更内容の詳細はリリースノートを参照してください。

2.0.0の目的

JavaScript Primerは、継続的にメンテナンスするためにOSSとして開発しています。 ECMAScriptの仕様は年に一度アップデートされていて、現実でのJavaScriptの使われ方も変化していくはずです。 ウェブ版は、毎日リリースできる形にして変化に対応する目的で更新しています。

1.0.0から2.0.0の間でも、100以上のコミットと24 contributorsによって更新されています。

スナップショットである書籍版はまだ2.0.0には対応していません。 2.0.0のリリース後もウェブ版は細かな変更が続くので、タイミングがいいときにスナップショットとして更新される予定(予定は未定)です。

ウェブ版は結構大体に書き換えることがあるので、安定したバージョンを求める人は時間をかけてチェックした書籍版を参照してください。 「JavaScriptとは」の章でも書いていますが、JavaScriptはかなり後方互換性が重視されている言語なので、書籍版で学んだことがすぐ使えなくなることはほぼないと思います。

JavaScript Primerがなぜ書かれているのかについては、次の記事でも詳しく紹介しています。

まだリリースしたばかりなのでバグなどが含まれているかもしれません。 もし読んでみてバグや間違いなどを見つけたら、ここを元にIssueとかPRだしてみてContributeに挑戦してみてください。

2.0.0での変更内容

2.0.0では主にECMAScript 2020の対応が含まれています。

この変更内容はRelease 2.0.0: ECMAScript 2020対応 · asciidwango/js-primerのリリースノートにも書かれています。

for-in mechanics

for...in文がプロパティを列挙する順番はES2019までは実装依存だった。 これがES2020では仕様として列挙する順番が規程されたので、異なる列挙をするブラウザは基本的になくなる。(現時点ではすでにどのブラウザも同じ順番) 背景としては、Reflect.ownKeys(ES2015)が入った際に大体の実装が同じ列挙順に統一されていた。 そのため実装依存だった順序の仕様を定義するように修正された。

詳細

export * as ns from "mod";

ES2020では、export * as ns from "mod";という再エクスポートの構文が追加された。

ES2015での見落とし的な構文で、ES2015では次のように書く必要があった。

import * as ns from "./module.js";
export { ns };

これを次のように1行で書けるように追加された構文。

export * as ns from "./module.js";

String.prototype.matchAll

ES2020では String.prototype.matchAll という正規表現のgフラグを使った繰り返しマッチに対応したメソッドが追加された。 今まではRegExp.prototype.execメソッドで繰り返しマッチを表現していたが、String.prototype.matchAllメソッドというIteratorを返すメソッドに置き換えることができる。

変更点

  • マッチした文字列の取得を書き直し
    • Sttring#matchString#matchAll をベースに変更
  • RegExp#execString#matchAll が利用できる場合に使う状況がないため、コラムに変更
    • RegExp#exec は 基本的には利用することはなくなったメソッドであるため
    • 既存のコードを読むと出てくる可能性はあるので、コラムとして残している(結構なトリッキーなコードでもある)
  • 基本は Sttring#matchString#matchAll の対比で話を進めた

globalThis

実行環境でwindowglobalなどグローバルオブジェクトの参照方法がバラバラだった。 これをまとめた概念としてglobalThisがES2020で追加された。

BigInt

新しいデータ型としてBigIntが追加された。

  • BigIntとは巨大な整数を表現するための新しいリテラル
  • 1n のように n というsuffixをつけるリテラル
  • 数値リテラルでは2^53-1よりも大きな値は精度が足りずに正確に表現できない
  • BigInt自体は7番目の新しいプリミティブ型として定義されている
  • そのため、typeofに"bigint"が追加されている
  • 浮動小数点表現にnをつけた場合は構文エラーとなる
  • BigIntの 0n も falsy に追加 #445

Nullish coalescing演算子(??)とOptional chaining(?.

Nullish coalescing演算子(??)は、左辺の値がnulishであるならば、右辺の評価結果を返す。 nulishとは、評価結果がnullまたはundefinedとなる値のこと。

Optional chaining演算子(?.)は、左辺のオペランドがnullish(nullまたはundefined)の場合は、それ以上評価せずにundefinedを返す。 一方で、プロパティが存在する場合は、そのプロパティの評価結果を返す。

どちらもNullishを扱うため、まとめて対応。

どちらの演算子も利用できる場所が広いため、かなり幅広いページを書き換えている。

変更点

  • falsyの説明を演算子の章に移動
    • falsyの対応としてnullishを演算子の章で解説するため
  • Optional chaining演算子の(?.)の解説を"オブジェクト"の章に追加
  • Nullish coalescing演算子(??)とOptional chaining(?.)の組み合わせを説明
  • Nullish coalescing演算子(??)の解説を"演算子"の章に追加
  • 一部のコードを ||?? に置き換え
    • 例としては問題ないけど、?? 推奨気味に変更

チートシートのES2020の対応

チートシートにES2020で増えた構文を追加。

  • Nullish coalescing演算子(??)
  • Optional chaining(?.
  • BigInt(42n)
  • export * as ns from "./x.js"

含まれなかったES2020の変更点

次のES2020の変更は、現時点のJavaScript Primerでは含まれていません。

  • Promise.allSettled
  • import()
  • import.meta

詳細はECMAScript 2020の対応 · Issue #1145 · asciidwango/js-primerを参照してください。