JavaScript Primerを出版しました!/JavaScript Primerはなぜ書かれたのか?
JavaScriptの入門書であるJavaScript Primerの書籍版が出版されました!
次のサイトから購入できます。
追記: 現在は改訂版が出ています → JavaScript Primer 改訂2版をリリースしました!/JavaScript Primerはなぜ更新され続けるのか? | Web Scratch
- 物理書籍
- 電子書籍
次のフォームからメールアドレスを登録しておけば、購入できるようになったら時点で通知します。 その他にも、メールを登録しておくと重要な変更があった場合などに通知します。
フォームが表示されない人は https://github.us13.list-manage.com/subscribe/post?u=fc41e11a2b9dc6f05350e0de0&id=7ab1594ae8 から登録できます。
JavaScript Primerとは
JavaScript Primerは、2015年に大きな変更があったECMAScript 2015を基本にして、現時点(2020-04-27)での最新であるECMAScript 2019を含むJavaScriptを一から学べる書籍です。 また既存のJavaScriptのコードを理解するためには、古い書き方についても知る必要があるため、必要に応じてそれらについても解説しています。
プログラミング経験のある人がJavaScriptという言語を新たに学ぶことを念頭に書かれています。 そのため、本当にプログラムが初めてという方には少しむずかしい部分はあります。 しかし、今は動画などでもJavaScriptの教材はたくさんあるので、他の教材と組み合わせて読むのが良いでしょう。
JavaScriptが扱う範囲はあまりに広大なので、一つの書籍/動画/サイトでJavaScriptをすべて学ぶのは不可能です。 そのため、複数のものを組み合わせてJavaScriptを学んでいくのがよいと思います。
また、JavaScript Primerは書籍版とウェブサイト版の内容は基本的には同じです。 書籍版は読み物として読みやすようにレイアウトなどが最適化されています。
https://jsprimer.net で公開しているウェブ版は誰でも無料で読めます。
書籍の内容もコードはMITライセンス、文章はCC BY-NC 4.0 CC BY 4.0(v5.0.0でライセンスを変更)で公開しているため、ライセンスの範囲内なら自由に扱えます。
ただし、電子書籍として販売されているPDFやepubなどの生成物はこのライセンスの範囲外なので、販売されているPDFなどをコピーして配るのは無理です。(あくまで内容についてのライセンスです)
出典がJavaScript Primerであると明記されているなら、文章やコードはそのままコピーして使えます。
また、CC BY-NCなのでそのまま再販のような営利目的の利用は駄目ですが、教育のための教材として利用することは可能です。
この辺の境界線はライセンスでは曖昧なので、必要に応じて問い合わせてください。
JavaScript Primer v5.0.0からライセンスをCC BYに変更し、商用利用でも自由に利用できるようになりました。 そのため、教材としての利用などは、著作者表示さえしていれば特に許可なくできます。
- JavaScript Primer v5.0.0: ES2023の対応/CC BYライセンスに変更/Open Collectiveで支援できるようになりました | Web Scratch
- 連絡先: Contact
JavaScript Primerはなぜ書かれたのか?
元々は付録で書こうとしていましたが、この記事ではJavaScript Primerがなぜ作られたのかについて見ていきます。
「はじめに」の章では、JavaScript Primerの目的を紹介していますが、 この記事ではもっと深く目的やなぜこの書籍が書かれているのかについて深堀りしています。
JavaScript Primerの目的
JavaScript Primerの目的は、JavaScriptというプログラミング言語を学ぶ必要が出てきた人が、一からJavaScriptを学べるようにすることです。 この「JavaScriptを学ぶ」には基本的な書き方を知るという意味もありますが、設計を考えてJavaScriptアプリケーションを作れるようになることも目的に含まれています。
また、JavaScriptはECMAScriptという仕様が毎年更新されているように、常に変化している言語です。 そのため、JavaScriptの変化に対して対応できるように学び方を学べる必要もありました。
最終的にこの書籍の実現するべき目的は大きく分けて次の3つとなりました。
- 書き方: 基本文法などのJavaScriptの書き方
- 作り方: JavaScriptを使ったアプリケーションの作り方
- 学び方: JavaScriptの進化を自分で知る学び方
これら3つを一冊の書籍で扱うため、基本を学びつつそれでいて現実のユースケースからは離れすぎないというバランスを一緒に扱うことを決めました。
なぜ「書き方」「作り方」「学び方」なのか? {#three-principle}
JavaScript Primerは2015-12-17から始まったプロジェクトです。 最初からOSSとして書籍を書くという目的だったので、すべてのミーティングログが公開されています。 (ミーティングログの書き方についてはミーティングログ/議事録の取り方についてのメモという記事を書きました)
最初期の2016-01-29のミーティングで書籍の内容をどうするべきかというミーティングで次のようなスライドを発表しています。
- スライド: ES6本
このスライドでは、この書籍がどのような目標で書かれるべきかを話しています。
事前にJavaScriptのレベル別書籍のまとめを調べた所、この時点ではES2015をベースにしたJavaScript初心者向けの書籍がありませんでした。
そこで新しいJavaScriptの書籍を作ろうという話が始まり、jsprimerは次のような目的で始まっています。
目的
• 現代的なJavaScriptについて理解できるようにする
• 「これ読んでおいて!」と渡せる書籍
• ES2015/ES2016...と言うような新しいものが出てきた時に 取り組める素養を作る
その中で、どんな書籍も最終的に学ぶJavaScriptという言語なのでそこは大きく変わらないはずです。そのため、書籍として学ぶ際のどのようにつまづきどころを減らすことに焦点をおいていました。
学ぶ際のフィードバックループとして、作りながら学ぶRuby入門では、学んだ文法でプログラムを作り改良点を検討するという話が書かれています。
jsprimerでも同じように、基本文法で学んだ知識をユースケースのアプリとして実装するという流れにするのがハマりどころを減らすことができると考えました。
一方でJavaScriptには膨大な機能なので最初にやらないことを決めておかないと収拾がつかないので、この時点ですべての機能を網羅することは目的外としました。
そのため、まず現実でのユースケースを考えて、そのユースケースを理解するために必要な文法を探すという逆説的な形で内容を決めていきました。
そして、最初の目的を満たすために、「書き方」「使い方」「学び方」を学べることが必要だろうという結論になりました。
Re:目的
• JavaScriptについて理解できるようにする
• →書き方(文法)を学ぶ
• JavaScriptで書かれたものを理解できるようにする
• →使い方(ユースケース)を学ぶ
• 新しいものが出てきたら時に取り組める素養を付ける
• →学び方を学ぶ
この3つの原則は書籍の構成にも現れています。 第一部の基本文法で「書き方」を学び、第二部のユースケースで「作り方」を学べるようになっています。
「学び方」は、章としてではなく全体的な流れとして取り入れることにしました。 なぜなら、「学び方」自体は学びたいことによっても異なる方法を取る場合があります。 そのため、「学び方」で個別の章とするよりは、他の章で「書き方」や「作り方」と一緒に見たほうがよいと考えたためです。
たとえば、基本文法などの学び方にはMDNのようなリファレンスサイトを見たほうがいいし、 アプリケーションの作り方は実際のサイトなどを参考にしたほうがよいためです。
第一部と第二部がどのように書かれたのかをざっくりと振りかえってみます。
第一部: 基本文法
第一部: 基本文法はJavaScriptの基本的な文法について扱っています。
プログラミングの入門書で文法については避けることはできませんが、この書籍も同様です。
しかしECMAScriptの仕様がどんどん巨大化しているため、すべての文法を紹介するのは無理があります。使わない機能も紹介していくと、無駄なはまりどころを増やしてしまうというのが見えていました。
そのため、この書籍の基本文法は引き算の考え方で書かれていて、入門として必要ないと判断したものはどんどん落としていっています。 また、最初の目的でも話したように、ユースケースがある基本文法を扱っているため、ユースケースがはっきりしてないものは省略しています。
省略した機能があることについては、第一部の終わりの章でも触れています。
基本文法で扱う機能(章)を決めたあとも章ごとのバランスを何度も調整しています。 特定の章に文量が偏ったり、特定の章に話が集中してしまうと読者がつまづくしまうポイントとなります。(たとえば、突然難しい章がでてくるとそこで読むのを諦めてしまうなど)
そのため、どうやったらなめらかに読めるかをベースに章の配分や順番は何度も調整しています。
たとえば、textstatという自作のツールを使って章ごとの分量を可視化して調整したり、章の依存関係(リンク)を調べて並び替えとかを行っています。
章ごとのファイルサイズ | 章の依存関係 |
---|---|
パフォーマンスチューニングも同じですが、処理の山(章の文量)が急に上がると体感が悪くなる(FPSが低下して画面がガクつくなど)ので、この山をなめらかにするイメージで調整していました。
文量は調整していますが、関数とthisや非同期処理:コールバック/Promise/Async Function のように長い章もあります。
これらの章は、this
やPromise
などの概念そのものが複雑なので、できるだけ丁寧に説明するために文量が増えてしまっています。
第一部全体で気をつけている部分として、基本文法であっても実際のユースケースから離れすぎないことです。 この書籍は文法を紹介するリファレンス本になるのが目的ではありません。(詳しくは「本書の目的ではないこと」を参照) そのため。必要な文法は紹介しつつ、実際の使われ方も合わせて紹介しています。
たとえば、「ループと反復処理」の章は、for
文などの反復処理について紹介しています。しかし反復処理においてfor
文やwhile
文についてだけを学ぶのは、文法的なグルーピングとしては正しいですが、現実とは少し離れています。
なぜなら現実ではArray#map
などのメソッドが使われることも多いからです。
そのため、この章ではfor
文などと対応する配列のメソッドでの書き方についても一緒に扱っています。また、現実のコードではどちらも使う機会があるので、どちらか一方が正しいわけではないという話もしています。
第一部: 基本文法は基本的には「書き方」を学べるように書いていますが、「学び方」については色々な章でちりばめて書いています。
たとえば、「文字列とUnicode」の章では、Unicodeの問題はJavaScriptに限定された問題ではないため、他の言語も参考できるという話をしています。 また、「ECMAScript」の章では、JavaScriptの仕様であるECMAScriptがどのように更新されているかやそのプロセスを解説しています。新しい機能を学ぶだけでなく、なぜその機能が追加されるのかについて考えてみようという話もしています。
あとは、エラーの読み方や調べ方、リファレンスとしてMDNも併用しましょうという話もしています。
この辺は実際にコードを書いていて問題が起きたときにどう直し方を見つけるかという部分を反映しています。
第二部: ユースケース
第二部: ユースケースでは、第一部: 基本文法で学んだことを生かして小さなアプリケーションを作りながら学べます。
第二部での一番の迷いどころは、どれぐらい現実のライブラリを使うかです。 現実のアプリケーションコードの97%はnpmからきたライブラリであるという話がある程度には、ライブラリの占める割合が大きいという話があります。
In fact, 97% of the code in a modern web application comes from npm.
そのため、JavaScriptを使ったアプリケーションの「作り方」を学ぶ上では、ライブラリを使うことは避けられません。
一方で、ライブラリがメジャーアップデートされるとコードの互換性がないことも多いため、書籍でライブラリを扱うのは難しいという問題があります。
この書籍はライブラリの使い方を学ぶのは目的ではありません。 あくまで学びたいのはライブラリの扱い方であって、別のライブラリであっても同じように扱えるようにすることが目的です。 そのため、ライブラリへの依存を最小限にしつつ、実際にライブラリをどう扱うかの工夫が必要でした。
ユースケース: Node.jsでCLIアプリケーションでは実際に著名なcommander
やmocha
などのライブラリを使ってCLIアプリを作成しています。それ以外のユースケースで使うローカルサーバーなどは書籍専用のものを作成してコントロールできるようにしています。
この書籍の最後の章はユースケース: Todoアプリです。 この書籍の目的は読み終わった時にちゃんとJavaScriptの設計ができることを目的としていました。
現実の設計にはモジュール化の概念は切り離すことができません。一方でモジュール化は書籍のような決まった枠がある2次元的なものだと見通しが悪くなりやすいので扱いにくい話題です。
そのため、できるだけ自然な流れでモジュールを取り入れたアプリケーション開発をしていく必要があり、設計をするにはリファクタリングも内容として含めたものを目指していました。 一方で、JavaScriptには統一的なUIフレームワークやコーディングスタイルなどは存在しません。しかし、これもJavaScriptらしさではあります。
JavaScriptは、癖を許さないとか制限がきついなどとは、まるで反対の立場だ。だから、効果的なプログラムを目指すJavaScript開発者は、ほかの大部分のプログラミング言語よりずっと、より良いスタイル、適切な使い方、ベストプラクティスを学び、追求する必要がある。
– Brendan Eich – Effective JavaScript
その中で、設計のプロトタイプとして使い古されているものとしてTodoMVCがあります。
このTodoアプリはさまざまなライブラリを使った実装が存在し、そのひとつの実装をこの書籍で書いてみるというのがゴールにマッチしていそうなのでこの題材にしました。 TodoMVC自体は、使い古されたものでありやや古い感じはありますが、ネットワークなど不必要で依存もなく紙面で扱いやすいのも理由のひとつです。
もっと同じようなひとつのテーマをもとにした複数の実装を見たい方はRealWorldやHackerNews クローンなどがあります。そこまでたどり着いているなら、この書籍のゴールである「設計について考える」ことができているはずです。
この書籍では何が学べないのか?
最後にこの書籍では何を学べないかについてです。
JavaScriptの変化に対応できる基礎を学ぶことを目的としています。 一方で、この書籍ではできるだけ変化しやすいものは排除するような構成にしています。 そのため、この書籍では次のことは学べません。
- 特定のライブラリやツールの使い方
- 未来のJavaScript
たとえばjQueryやReact、Angularなどのライブラリやフレームワーク、Babel、webpackなどのツールはこの書籍ではほとんど出てきません。 これらのライブラリやツールはJavaScriptのエコシステムを支える重要なものですが、とても変化が激しいです。
変化し続けるものを書籍という形で学ぶにはライフサイクルが合っていません。 学んでいるうちに別の変化が発生しています。 そのため、この書籍ではエコシステムの変化を表現しているライブラリやツールの使い方についてはかなり制限しています。
エコシステムの変化
なぜJavaScriptのエコシステムは変化をし続けているのか考えてみます。
ウェブブラウザやECMAScriptは、後方互換性を維持しつつ新しい機能を含んだアップデートを続けるという一見矛盾したものを両立することを選択しています。 エコシステムであるライブラリやツールはこの変化の中間にあるため、必然的に激しい変化が必要になります。
JavaScriptの複雑さは「変化をしつづけること」と「後方互換性を守る」の両方やろうとしていることからきているケースは多いです。 たとえば、新しい機能が特定のブラウザに実装されても、他のブラウザで利用できなければ使うことが難しいです。
これは2つの面からくる難しさです。 一つは単純に利用者のブラウザを制限してしまうため利用できなくなる環境があるという点です。 サーバ側の言語やツールと違って、ウェブサービスの運営者が新しい機能を使いたくても、エンドユーザーが使っているブラウザが古いまたは最新機能を実装していないと使えません。
もう一つは、ウェブ標準/ウェブブラウザでは相互運用性が重要視されるという点です。 かつてはブラウザ間でも相互運用性が悪い(つまり独占的なAPI)状態でした。 現在では、ここ数年で特定のブラウザの独自APIは整理され、かつての独自APIもウェブ標準として再定義するなど相互運用性の改善に取り組んでいます。 一方で、ここ1年はChrome特有のAPIが増加傾向にあります。
仕様策定の段階でも相互運用性は考慮されていて、ECMAScriptなら2つ以上の実装がないと仕様には入りません。 これは言い換えれば、特定のブラウザだけが新しい機能を実装しても、それはウェブ標準にならないため、そのうち消える可能性があります。 つまり、不安定なAPIに強く依存してしまうと、将来的な負債となる可能性を示しています。
この特定のブラウザでしか実装されていない新しいAPIや新しい機能を他のブラウザを動かす方法として、TrasnpilerのようなツールやPolyfillのようなライブラリがあります。 TranspilerやPolyfillは「変化をしつづけること」と「後方互換性を守る」の中間をつないでいるためとても複雑です。(実装的にも) さらに、これらのTranspilerやPolyfillを前提としたツールやライブラリがあるためさらに複雑化します。
これらのライブラリやツールは別のものが登場することによる移り変わりも存在しますが、同じツール自体がでも世の中の変化に応じて役割が変わるものもあります。
たとえば、webpackやbrowserifyといったbundlerと呼ばれるツールの初期の目的は、Node.js向けに書かれたnpmパッケージをブラウザで動かすことでした。 しかし、現在では最初からブラウザ向けのライブラリがnpmで公開されており、Node.js向けに書かれたものをブラウザで動かす(polyfill)するのが主目的ではなくなりました。 そのため、現在のBundlerはNode.jsモジュールをブラウザ向けにpack(polyfill)する役割から、モジュールを最適化してビルド(bundle)する役割へ変わってきています。
このようにツールの役割が時間で変化することもあります。 これはエコシステムを構成する部分的な変化です。
よく見る「JavaScriptは流行り廃りが激しい」という意見はエコシステムの中でも変化しやすい部分(特定のツールやライブラリ)を見ている可能性があります。 特定のツールやライブラリが別のものへと変化することはありますが、全体から見ると徐々に切り替わっているイメージです。 エコシステムは役割でモジュール化されているため、全体から見るとそこまで変わってないように見える部分かもしれません。
この書籍は、JavaScriptの変化に対応できる基礎を学ぶのが目的であるため、その変化しやすい特定のライブラリやツールについて学ぶのは避けています。 そのため、この書籍では新しいツールの使い方、新しいライブラリの使い方は学ぶことができません。 しかし、このようなエコシステムを構成するツールやライブラリは今のJavaScriptで書かれています。 これを読み解ける手助けをします。
ECMAScriptの仕様策定のプロセスがこの段階的な変化をよく表しています。 そのため、「変化していること」自体を学ぶ目的として「ECMAScript」の章では、ECMAScriptの策定プロセスやTranspiler、Polyfillの役割について紹介しています。
未来のJavaScript
未来のJavaScriptとは簡単にいえば、今策定されているECMAScript 2020やその先についてです。
JavaScript Primerは未来のJavaScriptについては言及しないようにしています。 これは、「はじめに」で書いていることと関係しています。
JavaScriptの文法といった書き方を学ぶことも重要ですが、実際にどのように使われているかを知ることも目的にしています。 なぜなら、JavaScriptのコードを読んだり書いたりするには、文法の知識だけでは足りないと考えているためです。
たとえば、現在Stage 3のClass field declarationsは、おそらくは将来のECMAScriptの仕様に入ると思いますが、 この構文/機能が現実の世界でどのように使われるかを予測するのは難しいです。 基本的にPrivate fieldsを使うようになるのかもしれませんし、思ったより使われない場合も考えられます。
また、ECMAScript 2018で入ったObject Rest/Spread構文は、構文的には既にあった「配列のRest/Spread構文のオブジェクト版」と言える仕様です。 この構文を紹介するのに「配列のRest/Spread構文のオブジェクト版」というのは正しいです。
しかし、現実ではこのObject Rest/Spread構文はReduxをはじめとしたステート管理ライブラリでの、Immutableなアップデート方法としてよく使われています。
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return { ...state, visibilityFilter: action.filter }
default:
return state
}
}
配列のRest/Spread構文でも同様のImmutableな更新が可能ですが、ObjectのRest/Spread構文ほど使われている印象はありません。 そのため、Object Rest/Spread構文を紹介する際には、「配列のRest/Spread構文のオブジェクト版」という紹介だけではなく、 Immutableなオブジェクトの更新/マージに使えるということについて触れるのが現実に沿っていると考えています。
JavaScript Primerはこのような現実での使われ方(ユースケース)を知ることが目的の一つです。 現実の使われ方がまだ決まっていない未来のJavaScriptについては意図的に扱わないようにしています。 そのため、この書籍では未来のことは学べません。未来については自分で考えてみてください。
なぜOSSなのか?なぜ無料で読めるのか?
JavaScript PrimerはOSSなプロジェクトです。ウェブサイト版もあるため無料で読めます。またGitHubでソースコードも公開しています。
jsprimerは最初からOSSで書くことを決めていて、その際にウェブ版を公開することも決めていました。 書籍をOSSで開発する理由としては、継続的にメンテンスするためです。また、無料で公開するのはどこからでも参照がしやすい教科書的なものが欲しかったからです。 初回のミーティングログでもこの目的が書かれています。
書籍の出版というライフサイクルだと、継続的に変化し続けるJavaScriptに対応していくのはとても難しいです。 少なくてもECMAScriptは年に一度アップデートされますし、現実でのJavaScriptの使われ方も微妙に変化していくはずです。 そのような変化に対して柔軟に対応していくためには、毎日リリースして変化に対応できるような状態でないといけません。
また、jsprimerは普通のライブラリやプロダクトと同じように誰でもContributeできます。 現時点(2020-04-26)でも80人以上の人がjsprimerにContributeしています。 jsprimerにはContribution Guideがあり、ユニットテストやtextlintでのテスト、E2Eでのテストなどもあります。文章がメインのプロジェクトですが、誰でも開発に参加できるような環境も整備しています。
現在もES2020にどう対応するかなどのIssueがあります。 興味がある人は、この機能に関する文章を書きたいとコメントしたり、ここは更新する必要があるといった指摘など、 普通のOSSと同じように参加できます。
また、JavaScript Primerは https://jsprimer.net/ というURLでウェブ版を無料で読めます。 ウェブ版を公開する一番の利点は、書籍の内容に対してリンクが貼れるという点です。 すべての目次に対してリンクが貼れるようになっているので、是非ウェブ版のjsprimerも活用してみてください!
jsprimerプロジェクトを応援するには次の方法があります。
リポジトリのGitHub Sponsorsボタンが設置されているのでそちらを参照してください。
自分のGitHub Sponsorsページは次のページからアクセスできます。
おわりに
JavaScript Primerのプロジェクトを開始してから5年弱程度経ちます。 最初のコミットはミーティングノートでした。
書籍版がリリースされたので、やっと1.0.0がリリースできました!
jsprimerを書く側のテーマの一つは、先ほども書いていた変化に対応する継続性です。 これからは特にどうやって継続的にアップデートしていくかに注視していく必要があります。
書籍のプロジェクトではJavaScript Promiseの本などいくつかやっていますが、 ライブラリなどに比べると機能追加(文章の追加)のContributeは珍しい印象です。
そのため新機能をContributeするのと同じレベルで、新しい文章を書けるContributorを増やせる状態にするのが継続性の鍵なのかなと思っています。 jsprimerはtextlintを使った自動チェックなど、文章周りにもCIの仕組みが充実させています。 また文章のレビューも色々やっているので、誰でも文章の追加がしやすいと思います。
Contributeしたい人は是非GitHub Issueにコメントしてください!
また、JavaScript Primerを読んだ感想やフィードバックも募集しているので、Issueを作ったりブログを書いて投稿したりするのも歓迎しています。
別の記事でリポジトリのCI/CD周りの仕組みについて書こうと思います。
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。