はじめに
JavaScriptを書けると思っている人は多いけど、本当に理解している人はどれくらいいるだろう、という話。
GitHub で184,000スター以上を獲得している「You Don't Know JS」は、JavaScriptの「なんとなく動いてる」を「完全に理解した」に変えてくれる書籍シリーズです。著者はKyle Simpson氏で、11年以上かけて執筆された渾身の作品。
正直なところ、最初は「また無料で読める技術書か」くらいに思っていたんですよ。でも読み始めたら、自分がいかにJavaScriptを表面的にしか理解していなかったか痛感させられました。30代になって思うのは、基礎を疎かにしたツケは必ず後で回ってくるということ。このシリーズはその基礎を徹底的に固めてくれます。
とはいえ、説明を読むより実際に動かして確かめた方が早いと思います。クロージャ、this、型強制(coercion)といったYou Don't Know JSの代表的なテーマを、ブラウザ上でその場で書き換えながら体感できるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
You Don't Know JSとは
「You Don't Know JS Yet」(通称YDKJS)は、JavaScriptの言語メカニズムを深掘りする書籍シリーズです。現在は第2版が展開されていて、すべてGitHub上で無料公開されています。
特徴的なのは、フレームワークやライブラリの使い方ではなく、JavaScript言語そのものの仕組みを解説していること。スコープ、クロージャ、プロトタイプ、非同期処理など、「なんとなく使えているけど説明できない」部分を徹底的に掘り下げてくれます。
Frontend Mastersがスポンサーとなっていて、Leanpubやamazonで電子書籍版も販売されています。ライセンスはCreative Commons Attribution-NonCommercial-NoDerivs 4.0です。
シリーズ構成
第2版の推奨される読む順序は以下の通りです。
1. Get Started(入門編)
JavaScriptとは何かから始まり、言語の全体像を掴むための入門書。これを読まずに次に進むのはもったいない。
2. Scope & Closures(スコープとクロージャ)
個人的には、これが一番衝撃を受けた巻。スコープチェーン、レキシカルスコープ、クロージャの仕組みが腹落ちします。
3. Objects & Classes(オブジェクトとクラス)
プロトタイプベースの継承、classキーワードの裏側、オブジェクト指向の本質を解説。現在ドラフト版として公開中。
4. Types & Grammar(型と文法)
JavaScriptの型システム、暗黙の型変換、文法の細かい部分を解説。粗ドラフト版として公開中。
特徴・メリット
1. 完全無料でアクセス可能
GitHub上で全文が公開されていて、いつでも無料で読めます。コスパ的に、これ以上のJavaScript学習リソースはなかなかない。
2. 「なぜ」を徹底的に解説
多くの入門書が「こう書けば動く」で終わるところ、YDKJSは「なぜそう動くのか」を解説してくれます。これ、意外と重要で、理由がわかると応用が効くようになるんですよね。
3. 実務で役立つ深い知識
面接で「クロージャを説明してください」と聞かれて困った経験、ありませんか。このシリーズを読めば、自信を持って答えられるようになります。
4. 段階的に深まる構成
Get Startedから始めて、徐々に深い内容に進む構成になっているので、挫折しにくい。時短で効率よく学べます。
5. 長年のメンテナンス
11年間にわたって更新され続けていて、184人以上のコントリビューターが参加しています。1,910以上のコミットがあり、品質が担保されています。
You Don't Know JSのサンプルを動かす
You Don't Know JSが扱っているのは、フレームワークのAPIではなくJavaScript言語そのものの仕組みです。なので、書籍で解説されている挙動はどれも素のJavaScriptとしてブラウザ上で実行して確かめられます。ここでは「Scope & Closures」で扱われるクロージャ、thisの解決ルール、「Types & Grammar」で扱われる型強制(coercion)の3つを、実際に値を書き換えながら動かせるサンプルとして用意しました。
クロージャの挙動を確認する
まず1つ目は、YDKJSの「Scope & Closures」で最も丁寧に解説されているクロージャです。makeCounterが返す内側の関数は、外側の関数が実行し終わったあともcount変数への参照を保持し続けます。これが「関数が自身のレキシカルスコープの外で実行されても、そのスコープを覚えている」というクロージャの本質です。
要点だけを抜き出すと、次のようになります。
function makeCounter() {
let count = 0
return function increment(step) {
count += step
return count
}
}
const counterA = makeCounter()
const counterB = makeCounter()
counterA(1) // 1
counterA(1) // 2
counterB(5) // 5 (counterAのcountとは別物)
下のサンプルでは、counterAとcounterBという2つの独立したクロージャを作り、それぞれのボタンで増分させています。加算するステップの数値も自由に変更可能です。
「counterAを実行」を何度押してもcounterBの値には影響しません。これはmakeCounterを呼び出すたびに、countを保持する新しいクロージャが生成されているからです。試しにコード中のlet count = 0をlet count = 100に書き換えて再実行すると、両方のカウンターの初期値が100からのスタートに変わることも確認できます。
thisの挙動を確認する
2つ目は、同じく「Scope & Closures」から「Objects & Classes」にかけて扱われるthisです。thisが何を指すかは関数がどこで定義されたかではなく、どう呼び出されたかで決まります。これを一番混乱しやすい4パターンで比較できるようにしました。
要点は次の通りです。
function ask(question) {
console.log(this.teacher, question)
}
const workshop1 = { teacher: 'Kyle', ask }
const workshop2 = { teacher: 'Suzy', ask }
workshop1.ask('question A') // Kyle question A
workshop2.ask('question B') // Suzy question B
const detachedAsk = workshop1.ask
detachedAsk('question C') // thisが失われ undefined になる
下のサンプルでは、オブジェクト経由での呼び出し・thisが外れた単独呼び出し・bindでthisを固定した呼び出しの3種類をボタンで比較できます。
「detachedAsk()」だけteacherが解決できず、thisが失われていることが分かるはずです。一方「boundAsk()」はworkshop1から切り離してもKyleのままになります。bind(workshop1)の部分をbind(workshop2)に変えると、固定されるthisがSuzy側に変わることも確認してみてください。
型強制(coercion)の挙動を確認する
3つ目は「Types & Grammar」の中心テーマである型強制(coercion)です。JavaScriptは+や==のように、演算子によって暗黙の型変換のルールが異なります。これを「なんとなく」で済ませず、入力値と演算子の組み合わせを自分で変えながら確認できるようにしました。
代表的な挙動は次の通りです。
'5' + 3 // "53" 文字列として連結される
'5' - 3 // 2 数値に変換されてから減算される
'5' == 5 // true 型を揃えてから値を比較する
'5' === 5 // false 型も含めて厳密に比較する
下のサンプルでは、2つの入力欄と演算子(+ - == ===)のセレクトを自由に組み合わせて、結果の値と型(typeof)を即座に確認できます。
opを==に、入力欄の片方の数字を変えるだけで、文字列と数値が型を揃えてから比較されている様子が分かります。逆に===に切り替えると、値が同じでも型が異なる限りfalseのままになることも確認できるはずです。ここで起きている暗黙の型変換のルールを体系的に解説しているのが、まさにYou Don't Know JSの「Types & Grammar」です。
読み始め方
オンラインで読む
GitHubリポジトリにアクセスすれば、すぐに読み始められます。
https://github.com/getify/You-Dont-Know-JS
第2版は 2nd-ed ブランチにあり、各書籍がディレクトリとして整理されています。
電子書籍を購入する
より読みやすい形式で欲しい場合は、LeanpubやAmazonで購入できます。著者を支援したい場合もこちらがおすすめ。
効果的な読み方
個人的には以下の順番をおすすめします。
- まず「Get Started」を通読して全体像を把握
- 「Scope & Closures」で基礎を固める
- 実際にコードを書きながら「Objects & Classes」へ
- 余裕があれば「Types & Grammar」で細かい部分を補完
具体的な学びのサンプル
実際にどんな内容が学べるのか、スコープとクロージャを例に見てみましょう。
スコープの理解
var teacher = "Kyle";
function otherClass() {
var teacher = "Suzy";
console.log("Welcome!");
}
function ask() {
var question = "Why?";
console.log(question);
}
otherClass(); // Welcome!
ask(); // Why?
このコードで、なぜotherClass内のteacherがグローバルのteacherを上書きしないのか。YDKJSを読めば、レキシカルスコープの仕組みから完全に理解できます。
クロージャの本質
function makeCounter() {
var count = 0;
return function increment() {
count = count + 1;
return count;
};
}
var counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
クロージャは「関数が自身のレキシカルスコープの外で実行されるとき、そのスコープへの参照を保持し続ける」という現象。この説明がスッと入ってくるようになります。
thisの理解
function ask(question) {
console.log(this.teacher, question);
}
var workshop1 = {
teacher: "Kyle",
ask: ask
};
var workshop2 = {
teacher: "Suzy",
ask: ask
};
workshop1.ask("How do I learn JS?");
// Kyle How do I learn JS?
workshop2.ask("What is closure?");
// Suzy What is closure?
thisが何を指すかは、関数が定義された場所ではなく、呼び出された方法で決まる。この理解があるかないかで、デバッグ効率が全然違います。
実践的なユースケース
JavaScript面接対策として
フロントエンドエンジニアの面接では、フレームワークの知識より言語の基礎知識を問われることが多い。YDKJSはその対策として一択ですね。
既存コードの理解に
レガシーコードを読むとき、「なぜこう書かれているのか」が理解できるようになります。プロトタイプチェーンや暗黙の型変換を理解していれば、古いコードも怖くない。
フレームワーク理解の土台として
React、Vue、Angularなど、どのフレームワークを使うにしても、JavaScript自体の理解が浅いと壁にぶつかります。YDKJSでその土台を固めておくと、フレームワークの学習効率も上がります。
コードレビューの質向上
「動くからいいでしょ」ではなく、「なぜこの書き方がベターなのか」を説明できるようになります。チーム内でのコードレビューの質がQOL上がります。
こんな人におすすめ
- JavaScriptを「なんとなく」使っている人
- フレームワークは使えるけど、言語自体の理解に不安がある人
- 面接でJavaScriptの深い質問をされて困った経験がある人
- 他人のコードを読んで「何やってるかわからない」と思うことがある人
- 基礎からしっかり学び直したい人
逆に、全くのプログラミング初心者には少しハードルが高いかもしれません。基本的な文法は理解している前提で書かれています。
まとめ
You Don't Know JSは、JavaScriptを「使える」から「理解している」にレベルアップさせてくれる稀有な書籍シリーズです。
GitHub Stars 184,000以上という数字が、その価値を物語っています。無料で読めるのにこのクオリティ、正直なところ有料の技術書と比べても遜色ない。むしろ上かもしれない。
30代になって技術書を読む時間も限られてくる中、本当に価値のある学習リソースを選びたい。YDKJSはその選択肢として、間違いなくトップクラスです。
スコープ、クロージャ、this、プロトタイプ。これらを「なんとなく」から「完全に理解」に変えたい人は、ぜひ読んでみてください。きっと、自分のJavaScript理解がいかに表面的だったか気づかされるはずです。