Skip to content

Releases: asciidwango/js-primer

v5.0.0: ES2023/CC BYライセンスに変更/Open Collective

31 Aug 00:50
@azu azu
e48a363
Compare
Choose a tag to compare

v5.0.0: ES2023

JavaScript Primer v5.0.0では、2023年6月27日にリリースされたECMAScript 2023(ES2023)をサポートしています。

Change Array by copy

概要

配列の破壊的なメソッドであるsplicereversesortに対して、
ES2023では非破壊的なバージョンであるtoSplicedtoReversedtoSortedが追加されました。

また、配列への代入(array[index] = item)という破壊的な処理に対して、withという非破壊的なメソッドが追加されました。

変更されたページ

変更内容

  • 破壊的なメソッドと非破壊的なメソッド のセクション
    • 追加されたtoSplicedtoReversedtoSortedwithメソッドの解説の追加
    • 破壊的な方法と非破壊的な方法の対応関係のテーブルを追加
破壊的な方法 非破壊な方法
array[index] = item Array.prototype.with[ES2023]
Array.prototype.pop array.slice(0, -1)array.at(-1)[ES2022]
Array.prototype.push [...array, item][ES2015]
Array.prototype.splice Array.prototype.toSpliced[ES2023]
Array.prototype.reverse Array.prototype.toReversed[ES2023]
Array.prototype.sort Array.prototype.toSorted[ES2023]
Array.prototype.shift array.slice(1)array.at(0)[ES2022]
Array.prototype.unshift [item, ...array][ES2015]
Array.prototype.copyWithin[ES2015] なし
Array.prototype.fill[ES2015] なし

配列のメソッドを非破壊的なメソッド(Immutable)と破壊的なメソッド(Mutable)に分けると、次のようになります。

非破壊的なメソッドと破壊的なメソッド

関連

Array.prototype.{findLast, findLastIndex}

概要

ES2023では、Array.prototype.findIndexArray.prototype.find に対応するメソッドとして、
Array.prototype.findLastIndexArray.prototype.findLastが追加されました。

それぞれ findIndexfind と同じ使い方ですが、末尾から探索した結果を返すメソッドになっています。

変更されたページ

変更点

  • ES2023で追加された Array.prototype.findLastIndexArray.prototype.findLast の対応
  • Array.prototype.lastIndexOf のサンプルコードを追加

関連

Symbols as WeakMap keys

概要

ES2022までは、WeakMapのキーとWeakSetの値にはオブジェクトのみが指定可能でした。
これは弱い参照をGCで解放するために、キーは一意な値のみが指定可能という制限からくるものでした。
Symbolも一意な値となるため、ES2023ではオブジェクトに加えてSymbolも指定できるように仕様が変更されました。

変更されたページ

変更内容

  • WeakMapのキーに指定可能なものとしてSymbolを追加
  • WeakSetの値に指定可能なものとしてSymbolを追加

関連

その他のProposal

その他にもES2023にマージされたProposalとしてHashbang Grammarがあります。
Hashbang Grammarは#!から始まる最初の行をコメントとして扱う仕様ですが、Node.jsなどの実行環境との相互運用性を考慮して、ES2023で仕様が変更されました。
jsprimerでは特に取り扱っていませんが、興味がある方は次のIssueを参照してください。

ライセンスの変更

今までのjsprimerのライセンスは次のとおりでした。

  • ソースコード: MITライセンス
  • 文章: CC BY-NC 4.0

v5.0.0からはjsprimerのライセンスを次のように変更します。

  • ソースコード: MITライセンス(そのまま)
  • 文章: CC BY 4.0

CC BY-NCでは商用利用を禁止する条項がありますが、
CC BYにはこの条項は含まれません。

行為 CC BY CC BY-NC
複製 OK OK
頒布 OK OK
展示 OK OK
実演 OK OK
改変 OK OK
著作権者の表示 必要 必要
非営利目的 OK NG

元から、教材などとしての利用は許可していましたが、商用かどうかの判断が難しいものになっていました。
今回の変更で、著作権者表示をすれば商用でも利用可能なライセンスになっています。
これにより、jsprimerの文章も、より自由に使いやすくなります。

変更の詳細についてはIssueを参照してください。

Open Collectiveでjsprimerを支援できるようになりました

BabelやPrettierなども利用しているOpen Collectiveというサービスを使い、JavaScript Primerというプロジェクトを金銭的に支援できるようになりました。

次のCollectiveのページから支援できるようになっています。

このOpen Collectiveでの支援は、主に企業ユーザーを対象にしています。
支援することでWebサイトや次回(ES2024)のリリースノートにスポンサー表示ができるようになります。
また、"推しページ"を設定できるようにする予定で、https://jsprimer.net/の特定のページにメッセージ(書籍のポップをイメージ)を出せるようにする予定です。

JavaScript Primerは変化を前提にした書籍のプロジェクトであるため、毎年のECMAScriptのリリースに合わせて内容を改訂しています。
jsprimerは変化に対応できる基礎を身につけられること、またそれを迷わずに学べるようにすることを目的にしたプロジェクトです。
変化に対応するには、書籍自体も変化に対応する必要があります。

更新に継続的に行うのに必要なリソースとしてヒト、カネ、モノがあります。
Open Collectiveは、プロジェクトに対して金銭的な支援をすることができるサービスです。
単純に受け取るだけではなく、プロジェクトにContributeしてくれた方に還元することもできます。
それらのやりとりがオープンに行えるのがOpen Collectiveの特徴です。

ざっくりとした試算では、jsprimerの毎年の更新にかかる必要は年間で687,840円ぐらいです。
詳細は次の記事にまとめています。

JavaScript Primer - Open Collectiveでの支援方法として、Yearly Gold Sponsors(年間)とMonthly Gold Sponsors(月間)を用意しています。
jsprimerは年ごとの更新なので、Yearly Gold Sponsorsがわかりやすいかと思います。

まだ、どういう形が最適なのかはわかっていないため、Contributeしてくれる方(金銭的な支援もContributeです)と考えながら形を作っていけければと思います。
次のページに、このリリースについてのDiscussionを用意しているので、是非で意見を聞かせてください!

Open Collectiveについてはまだ検討中の部分も多いので、まずは公開するところから始めています。
これからも更新されていくと思うので、更新情報を知りたい方は、リポジトリをWatchしてみてください。

Watch

https://github.com/asciidwango/js-primer からWatchボタンで、Releaseの更新情報を受け取れます。

また、メールで通知を受け取りたい方は、次のフォームからメールアドレスを登録すると更新情報を受け取れます。

v4.0.0の書籍版のスナップショット

18 May 00:41
@azu azu
2467fdf
Compare
Choose a tag to compare

v4.0.0: ES2022

22 Jun 12:52
@azu azu
Compare
Choose a tag to compare

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

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メソッド内で値を代入する必要がありました。クラスフィールドでは、インスタンスへのプロパティの定義をより宣言的に行えます。

また、Privateクラスフィールドでは # という新しい記号を利用します。
そのため、今までprototypeの省略記号として # を利用していた部分は全て書き換えています。

その他

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

ウェブエディタの改善

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

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

image

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

最初にjsprimerでは、書籍をよりよくしていくための改善案などは常に募集しています。
また、今回のアップデートに関連して特に意見を募集している箇所はDiscussionのスレッドを作成しているので、興味がある人はコメントしてくダサい。

3.0.0: ECMAScript 2021対応

27 Jun 15:04
@azu azu
Compare
Choose a tag to compare

3.0.0

JavaScript Primerのウェブ版がECMAScript 2021に対応しました 🎉

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

JavaScript Primerについて

JavaScript Primerは、これからJavaScriptを学びたい人が、ECMAScript 2015以降をベースにして一からJavaScriptを学べる書籍です。
ECMAScriptの仕様は毎年アップデートされるため、JavaScript Primerも毎年それに対応できるように継続してアップデートしています。

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

GitHub Watchesの登録画面

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

書籍への支援について

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

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

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

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

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

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

ECMAScript 2021

The 121st General Assembly held as a virtual meeting on 22 June 2021 approved the following documents:

ECMA-262 12th edition – ECMAScript® 2021 language specification
-- https://www.ecma-international.org/news/ecma-international-approves-new-standards-4/

ECMAScript 2021は、2021年6月にEcma Internationalで正式に承認された仕様です。
ECMAScriptの仕様策定のプロセスについては、次のページを参照してください。

3.0.0の変更点

3.0.0では次の項目について書籍の内容を変更、追加しています。

String#replaceAll

ES2021では、String#replaceAllメソッドというマッチした文字列を全て置換するメソッドが追加されました。
String#replaceメソッドは、最初に一致したものだけが置換されますが、String#replaceAllメソッドでは一致したものがすべて置換されます。

今までもString#replaceメソッドと正規表現のg(global)フラグを使うことで、繰り返し置換が可能でした。
しかし、正規表現では?.などは特殊な意味を持つため、エスケープが必要となります。
String#replaceAllメソッドでは、ただの文字列として渡したものを繰り返し置換ができるため、エスケープが不要な点が主な違いです。

const str = "???";
// replaceメソッドの場合は、正規表現の特殊文字はエスケープが必要となる
console.log(str.replace(/\?/g, "!")); // => "!!!"
// replaceAllメソッドでは、文字列として渡した検索文字列を全て置換する
console.log(str.replaceAll("?", "!")); // => "!!!"

詳細

Numeric Separators

ES2021では、Numeric Separatorsという_を数値リテラルの区切り文字として利用できる構文が追加されました。

数値リテラルでは数値が大きくなるほど、桁数の見間違いなどが発生しやすくなります。

const largeNumber = 1000000000000;

Numeric Separatorsでは、数値リテラルの区切り文字として_が追加できます。
数値リテラルを評価する際には、_は単純に無視されるため意味の違いはありません。

const largeNumber = 1_000_000_000_000;

JavaScript Primer 3.0では、このNumeric Separatorsの解説をデータ型とリテラルに追加しています。

また、ビット演算では数値リテラルの桁数が多くなりやすいです。
そのため、演算子のビット演算のセクションをNumeric Separatorsを使って書き直し、図などを入れています。

📝 演算子の章は肥大化しやすいので、今後のバージョンで整理するかもしれません。
ビット演算はユースケースでは利用していないため、ページとして分ける可能性もありそうです。

チートシートのES2021の対応

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

  • Numeric Separators

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

次のES2021の変更は、現時点のJavaScript Primerでは含まれていません。
JavaScriptのリファレンスを作ることは本書の目的ではないため、
この本のユースケースで利用する可能性が少ないものに関しては取り入れていません。

  • Promise.anyAggregateError
  • WeakRefs
  • Logical assignment operators
    • &&=||=??= のような論理演算子と代入演算子の組み合わせ
    • コメント: #1220 (comment)
    • 仮PR: #1334

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

その他の修正

2.0.0: ECMAScript 2020対応

01 Sep 04:37
@azu azu
Compare
Choose a tag to compare

2.0.0

JavaScript Primerのウェブ版をECMAScript 2020に対応しました 🎉

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

ECMAScript 2020

The 119th General Assembly held as a virtual meeting on June 16, 2020, approved the following documents:
ECMA-262 11th edition - ECMAScript® 2020 Language Specification
ECMA-402 7th edition - ECMAScript® 2020 Internationalization API Specification

ECMAScript 2020は2020年06月にEcma Internationalによって正式に承認された仕様です。
ECMAScriptの仕様策定のプロセスについては次のページを参照してください。

2.0.0の変更点

2.0.0では次の項目についてそれぞれ書籍の内容を変更、追加しています。

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を参照してください。

1.0.0

24 Apr 00:50
@azu azu
Compare
Choose a tag to compare

書籍版の初版をリリース

JavaScript Primerは これからJavaScriptに入門したい人が、ECMAScript 2015以降をベースにして一からJavaScriptを学べる書籍です。
プログラミングをやったことがあるが、今のJavaScriptがよくわからないという人が、 今のJavaScriptアプリケーションを読み書きできるようになるように書かれています。