はじめに
本書は、コンピュータに自分の望むことをさせる方法についての書籍です。今日のコンピュータはドライバーとほぼ同じくらい一般的ですが、はるかに多くの隠れた複雑さを含んでいるため、操作と理解が困難です。多くの人にとって、それらは異質で、やや脅威的な存在のままです。

私たちは、社会性と空間的推論の才能を持つ私たちのような柔らかな生物と、無意味なデータを無情に操作するコンピュータの間のコミュニケーションギャップを埋めるための2つの効果的な方法を見つけました。1つ目は、物理的な世界への感覚に訴え、その世界を模倣し、指で画面上の形状を操作できるようにするインターフェースを構築することです。これは、カジュアルな機械とのインタラクションに非常に有効です。
しかし、インターフェースの設計者が想定していなかったことをコンピュータに伝えるために、ポイントアンドクリックアプローチをうまく利用する方法はまだ見つかっていません。任意のタスクを実行するようにコンピュータに指示するなど、オープンエンドのインターフェースの場合、私たちの言語能力を利用するアプローチの方が成功しています。それは、機械に言語を教えることです。
人間の言語では、単語やフレーズをさまざまな方法で組み合わせることができ、さまざまなことを言うことができます。コンピュータ言語は、通常、文法的に柔軟性が低いものの、同様の原則に従います。
過去20年間でカジュアルコンピューティングははるかに普及し、かつては人々がコンピュータとやり取りするデフォルトの方法であった言語ベースのインターフェースは、グラフィカルインターフェースに大きく取って代わられました。しかし、それらはまだ存在し、場所が分かれば見つけることができます。そのような言語の1つであるJavaScriptは、ほぼすべてのWebブラウザに組み込まれており、ほぼすべての民生用デバイスで使用できます。
本書は、コンピュータに自分の望むことをさせることができるようになるのに十分なこの言語の知識を身につけることを目的としています。
プログラミングについて
学ぶ意欲のない者には教えず、自ら説明しようとしない者には刺激を与えません。もし私が正方形の一つの角を示したのに、彼らが残りの三つの角を持って戻ってこないなら、私はその点を再び説明すべきではありません。
JavaScriptを説明することに加えて、プログラミングの基本原則についても紹介します。プログラミングは、実際には難しいです。基本的な規則は通常、シンプルで明確です。しかし、これらの規則の上に構築されたプログラムは、独自の規則と複雑さを導入するほど複雑になりがちです。ある意味、自分の迷路を構築しており、迷ってしまうかもしれません。
本書を読む際に非常にイライラすることがあるでしょう。プログラミング初心者であれば、消化すべき新しい情報がたくさんあります。これらの情報の多くは、追加のつながりを必要とする方法で組み合わせられます。
必要な努力をするのはあなた次第です。本書の内容を理解するのに苦労している場合は、自分の能力について結論を急がないでください。あなたは大丈夫ですよ—続けるだけでいいのです。休憩を取り、一部の内容を読み直し、常にサンプルプログラムと演習を読んで理解してください。学習は大変な作業ですが、学習したことはすべてあなたのものとなり、その後の学習を容易にします。
コンピュータプログラマは、彼[sic]だけが責任を負う宇宙の創造者です。事実上無限の複雑さを備えた宇宙は、コンピュータプログラムの形で作成できます。
プログラムは多くのものです。それはプログラマによってタイプされたテキストの一部であり、コンピュータに動作させる指令であり、コンピュータのメモリ内のデータであり、そしてこの同じメモリで実行される動作を制御します。プログラムを私たちがよく知っているオブジェクトと比較しようとするアナロジーは、不十分になりがちです。表面的に適切なものは機械です—多くの別々の部品が関与する傾向があり、全体を動かすためには、これらの部品がどのように相互接続し、全体の動作に貢献するかを検討する必要があります。
コンピュータは、これらの非物質的な機械のホストとして機能するように構築された機械です。コンピュータ自体は、愚かで単純な作業しかできません。それらが非常に役立つ理由は、これらの作業を信じられないほどの高速で実行することです。プログラムは、これらの単純な動作を膨大な数巧妙に組み合わせることで、非常に複雑な作業を行うことができます。
私たちの中には、コンピュータプログラムを書くことを魅力的なゲームと考えている人もいます。プログラムは思考の構築物です。構築にかかる費用はゼロで、重量がなく、私たちのタイピングの手の下で簡単に成長します。
しかし、注意しないと、プログラムのサイズと複雑さが制御不能に増大し、作成者でさえ混乱させるでしょう。プログラムを制御することは、プログラミングの主要な問題です。プログラムが機能すると、それは美しいものです。プログラミングの芸術は、複雑さを制御するスキルです。優れたプログラムは控えめであり—その複雑さの中でシンプルに作られています。
多くのプログラマは、この複雑さは、プログラムでよく理解されている少数のテクニックのみを使用することで最適に管理されると考えています。彼らは、プログラムが持つべき形式を規定する厳格な規則(「ベストプラクティス」)を制定しており、熱心な人の中には、この安全な小さな領域の外に出る人を悪いプログラマと見なす人もいます。
プログラミングの豊かさへの敵意—それを単純で予測可能なものにすること、奇妙で美しいすべてのプログラムにタブーを置くこと!プログラミング技術の領域は膨大であり、その多様性において魅力的で、まだ大部分が未開拓です。それは確かに危険な旅であり、経験の浅いプログラマをあらゆる種類の混乱に誘いますが、それは慎重に進み、機転を利かせる必要があることを意味するだけです。学ぶにつれて、常に新しい課題と探検すべき新しい領域が現れます。探検をやめようとするプログラマは停滞し、喜びを忘れ、仕事に飽きてしまうでしょう。
言語が重要な理由
計算の誕生当初、プログラミング言語はありませんでした。プログラムは次のようなものに見えました。
00110001 00000000 00000000 00110001 00000001 00000001 00110011 00000001 00000010 01010001 00001011 00000010 00100010 00000010 00001000 01000011 00000001 00000000 01000001 00000001 00000001 00010000 00000010 00000000 01100010 00000000 00000000
これは、1から10までの数字を合計し、結果(1 + 2 + ... + 10 = 55
)を出力するプログラムです。これは単純な仮想マシン上で実行できます。初期のコンピュータをプログラムするには、多数のスイッチを正しい位置に設定するか、厚紙に穴を開けてコンピュータに供給する必要がありました。この手順がいかに面倒でエラーが発生しやすいものだったかは想像できるでしょう。単純なプログラムを書くことさえ、多くの巧妙さと規律が必要でした。複雑なものはほとんど考えられませんでした。
もちろん、これらの難解なビットパターン(1と0)を手動で入力することで、プログラマは強力な魔法使いであるという深い感覚を得ることができました。そして、それは仕事の満足度という意味で価値があるはずです。
前のプログラムの各行には、1つの命令が含まれています。それは次のように英語で書くことができます。
1. Store the number 0 in memory location 0. 2. Store the number 1 in memory location 1. 3. Store the value of memory location 1 in memory location 2. 4. Subtract the number 11 from the value in memory location 2. 5. If the value in memory location 2 is the number 0, continue with instruction 9. 6. Add the value of memory location 1 to memory location 0. 7. Add the number 1 to the value of memory location 1. 8. Continue with instruction 3. 9. Output the value of memory location 0.
それはすでにビットのスープよりも読みやすいですが、まだかなり不快です。命令とメモリ位置に数字の代わりに名前を使用すると役立つ場合があります。
Set “total” to 0. Set “count” to 1. [loop] Set “compare” to “count”. Subtract 11 from “compare”. If “compare” is zero, continue at [end]. Add “count” to “total”. Add 1 to “count”. Continue at [loop]. [end] Output “total”.
この時点でプログラムがどのように機能するか分かりますか?最初の2行は、2つのメモリ位置に初期値を与えます。total
は計算の結果を積み上げるために使用され、count
は現在見ている数を追跡するために使用されます。compare
を使用する行はおそらく最も奇妙なものです。プログラムは、実行を停止できるかどうかを判断するために、count
が11と等しいかどうかを確認したいと考えています。私たちの仮想マシンは非常にプリミティブであるため、数値がゼロかどうかのみをテストし、それに基づいて決定(またはジャンプ)を行うことができます。そのため、compare
というラベルの付いたメモリ位置を使用してcount - 11
の値を計算し、その値に基づいて決定を行います。次の2行は、プログラムがまだcount
が11ではないと決定するたびに、結果にcount
の値を追加し、count
を1ずつ増分します。
var total = 0, count = 1; while (count <= 10) { total += count; count += 1; } console.log(total); // → 55
このバージョンでは、さらにいくつかの改良が加えられています。最も重要なのは、プログラムを行ったり来たりさせる方法を指定する必要がなくなったことです。while
言語構造がそれを処理します。与えられた条件が成立する限り、その下の(中括弧で囲まれた)ブロックの実行を続けます。その条件はcount <= 10
であり、「count
は10以下」という意味です。もはや一時的な値を作成してゼロと比較する必要がなくなり、それは面白くない詳細でした。プログラミング言語の力の1つは、面白くない詳細を処理してくれることです。
プログラムの終了後、while
構文が終了した後に、結果を出力するためにconsole.log
操作が適用されます。
最後に、もし便利なrange
とsum
操作が利用可能であれば、プログラムはどのように見えるかを示します。これらはそれぞれ、範囲内の数値のコレクションを作成し、数値のコレクションの合計を計算します。
console.log(sum(range(1, 10))); // → 55
この教訓は、同じプログラムが長く、短く、読みにくく、読みやすく表現できるということです。プログラムの最初のバージョンは非常に分かりにくかったのに対し、最後のバージョンはほぼ英語です。1から10までの数値のrange
のsum
をlog
する。(sum
やrange
のような操作をどのように構築するかは、以降の章で説明します。)
優れたプログラミング言語は、コンピュータが実行する必要がある動作についてより高いレベルで記述できるようにすることで、プログラマを支援します。それは、興味のない詳細を省略し、便利な構成要素(while
やconsole.log
など)を提供し、独自の構成要素(sum
やrange
など)を定義することを可能にし、それらの構成要素を簡単に組み合わせることができます。
JavaScriptとは何か?
JavaScriptは、1995年にNetscape Navigatorブラウザのウェブページにプログラムを追加する方法として導入されました。その後、この言語は他の主要なグラフィカルウェブブラウザすべてで採用されています。これにより、現代のウェブアプリケーションが可能になりました。これは、あらゆる操作でページを再読み込みすることなく、直接対話できるアプリケーションです。しかし、それはより伝統的なウェブサイトでも、様々なインタラクティブ性と巧妙さを提供するために使用されています。
JavaScriptは、Javaという名前のプログラミング言語とほとんど関係がないことに注意することが重要です。似た名前は、優れた判断力ではなく、マーケティング上の考慮から付けられました。JavaScriptが導入された当時、Java言語は盛んにマーケティングされ、人気が高まっていました。この成功に便乗しようという考えが誰かにあったのです。今では、その名前のままになっています。
Netscape以外での採用後、JavaScript言語の動作方法を記述する標準文書が作成され、JavaScriptをサポートすると主張する様々なソフトウェアが実際に同じ言語について話していることを確認しました。これは、標準化を行ったEcma International組織にちなんで、ECMAScript標準と呼ばれています。実際には、ECMAScriptとJavaScriptという用語は互換的に使用できます。これらは同じ言語の2つの名前です。
JavaScript言語について「ひどい」ことを言う人もいます。これらの多くのことは事実です。初めてJavaScriptで何かを書く必要があったとき、私はすぐにそれを嫌うようになりました。それは私がタイプしたほとんど何でも受け入れるのですが、私が意図したのとは全く異なる方法で解釈するのです。もちろん、これは私が何をやっているのか全く分からなかったという事実と大きく関係していますが、ここで真の問題があります。JavaScriptは許容範囲がばかげて寛大なのです。この設計の背後にある考えは、JavaScriptでのプログラミングを初心者にとってより簡単にすることでした。実際には、システムがそれらを指摘してくれないため、プログラムの問題を見つけるのが難しくなるだけです。
しかし、この柔軟性にも利点があります。それは、より厳格な言語では不可能な多くの技術のためのスペースを残し、(例えば第10章でわかるように)JavaScriptの欠点を克服するために使用することができます。この言語を正しく学習し、しばらくの間使用してきた後、私は実際にJavaScriptを好きになりました。
JavaScriptにはいくつかのバージョンがあります。ECMAScriptバージョン3は、JavaScriptが支配的地位に上り詰めた頃、およそ2000年から2010年までの間、広くサポートされていました。この間、言語に多くの抜本的な改善と拡張を計画した野心的なバージョン4の作業が進められていました。生きている広く使用されている言語をこのような抜本的な方法で変更することは、政治的に困難であることが判明し、バージョン4の作業は2008年に中止され、はるかに野心のないバージョン5が2009年にリリースされました。現在、すべての主要ブラウザがバージョン5をサポートしており、この本ではこの言語バージョンに焦点を当てます。バージョン6は最終段階にあり、一部のブラウザは既にこのバージョンの新機能のサポートを開始しています。
ウェブブラウザは、JavaScriptが使用される唯一のプラットフォームではありません。MongoDBやCouchDBなどのデータベースは、スクリプト言語およびクエリ言語としてJavaScriptを使用しています。デスクトップおよびサーバプログラミングのためのいくつかのプラットフォーム、特にNode.jsプロジェクト(第20章の主題)は、ブラウザの外でJavaScriptをプログラミングするための強力な環境を提供しています。
コードとその扱い方
コードとは、プログラムを構成するテキストです。この本のほとんどの章には、かなりの量のコードが含まれています。私の経験では、コードを読むこととコードを書くことはプログラミングを学ぶ上で不可欠な部分であるため、例をざっと見るだけにすることは避けてください。注意深く読んで理解してください。最初は遅くて混乱するかもしれませんが、すぐに慣れると約束します。演習についても同様です。実際に動作するソリューションを作成するまで、理解していると仮定しないでください。
実際のJavaScriptインタプリタで演習の解答を試すことをお勧めします。そうすれば、自分がやっていることが機能しているかどうかについてすぐにフィードバックを得ることができ、演習を超えて実験しようという誘惑を受けるでしょう。
この本をブラウザで読むときは、例題プログラムをクリックして編集(実行)できます。
この本で定義されているプログラムを本のサンドボックスの外で実行したい場合は、注意が必要です。多くの例は独立しており、どのJavaScript環境でも動作するはずです。しかし、後の章のコードは、主に特定の環境(ブラウザまたはNode.js)用に記述されており、そこでしか実行できません。さらに、多くの章ではより大きなプログラムを定義しており、そこに表示されるコードの部分は互いに依存しているか、または外部ファイルに依存しています。ウェブサイトのサンドボックスには、特定の章のコードを実行するために必要なすべてのスクリプトとデータファイルを含むZipファイルへのリンクが提供されています。
本書の概要
本書はおよそ3部構成になっています。最初の11章ではJavaScript言語自体について説明します。次の8章は、ウェブブラウザとJavaScriptを使用してそれらをプログラムする方法についてです。最後に、2つの章は、JavaScriptをプログラムするもう1つの環境であるNode.jsに費やされています。
本書全体を通して、実際のプログラミングの雰囲気を味わうための、より大規模な例題プログラムを説明する5つのプロジェクト章があります。順番に、人工生命シミュレーション、プログラミング言語、プラットフォームゲーム、ペイントプログラム、動的なウェブサイトを作成していきます。
本書の言語部分は、JavaScript言語の基本的な構造を紹介する4つの章から始まります。これらでは、制御構造(この導入で見たwhile
キーワードなど)、関数(独自の操作を作成)、およびデータ構造を紹介します。これらを読めば、簡単なプログラムを作成できるようになります。次に、第5章と第6章では、関数とオブジェクトを使用してより抽象的なコードを作成し、複雑さを制御する方法を紹介します。
最初のプロジェクト章の後、本書の最初の部分は、エラー処理と修正、正規表現(テキストデータの処理に重要なツール)、およびモジュール性(複雑さに対抗するもう1つの武器)に関する章が続きます。2つ目のプロジェクト章で本書の最初の部分が終了します。
第2部(第12章から第19章)では、ブラウザのJavaScriptがアクセスできるツールについて説明します。画面に何かを表示する方法(第13章と第16章)、ユーザー入力に応答する方法(第14章と第18章)、ネットワークを介して通信する方法(第17章)を学びます。この部分にも2つのプロジェクト章があります。
その後、第20章でNode.jsについて説明し、第21章でそのツールを使用して簡単なウェブシステムを構築します。
文字表記規則
本書では、`等幅`フォントで記述されたテキストはプログラムの要素を表します。これらは独立した断片である場合もあれば、近くのプログラムの一部を参照している場合もあります。プログラム(既にいくつか見たもの)は、次のように記述されます。
function fac(n) { if (n == 0) return 1; else return fac(n - 1) * n; }
プログラムが出力する出力を示すために、期待される出力がその後に、2つのスラッシュと矢印を前に付けて記述される場合があります。
console.log(fac(8)); // → 40320