第1章: はじめに

パーソナルコンピュータが最初に登場したとき、ほとんどのコンピュータには、通常はBASICの変種である単純なプログラミング言語が搭載されていました。コンピュータとのインタラクションはこの言語と密接に統合されていたため、コンピュータユーザーは、望んでいようがいまいが、その味を味わうことになりました。コンピュータが豊富で安価になった現在では、一般的なユーザーはマウスでクリックする以上のことをすることはありません。ほとんどの人にとっては、これは非常にうまく機能します。しかし、技術的ないじくり回すことに自然な傾向のある私たちにとっては、日常的なコンピュータ使用からプログラミングが排除されたことは、ある種の障壁となっています。

幸いなことに、World Wide Webの発展の結果として、最新のウェブブラウザを搭載したすべてのコンピュータには、JavaScriptをプログラミングするための環境があることがわかりました。今日のユーザーを技術的な詳細に悩ませないという精神において、それはうまく隠されていますが、ウェブページはそれをアクセス可能にし、プログラミングを学ぶためのプラットフォームとして使用することができます。

この(ハイパー)ブックは、まさにそれを試みています。


学ぶことに熱心でない者を啓発することも、自ら説明することに熱心でない者を奮い立たせることもありません。もし私が四角の一隅を示したのに、残りの三隅を持って私のところに帰ってこないならば、私はその点を再び繰り返すことはありません。

― 孔子

この本はJavaScriptを説明するだけでなく、プログラミングの基本原則を紹介することを試みています。プログラミングは、実際には難しいものです。基本的なルールは、ほとんどの場合、シンプルで明確です。しかし、これらの基本的なルールの上に構築されたプログラムは、独自のルール、独自の複雑さを導入するほど複雑になりがちです。このため、プログラミングはめったにシンプルでも予測可能でもありません。この分野の創設者の一人であるDonald Knuthが言うように、それは芸術です。

この本から何かを得るには、受動的な読書以上のものが必要です。鋭さを保ち、練習問題を解く努力をし、前の資料をある程度理解したと確信してから先に進んでください。


コンピュータプログラマは、彼自身だけが責任を負う宇宙の創造者です。事実上無限の複雑さの宇宙は、コンピュータプログラムの形で創造することができます。

― Joseph Weizenbaum、『Computer Power and Human Reason』

プログラムは多くのものです。それはプログラマによってタイプされたテキストの一部であり、コンピュータに動作させる指示力であり、コンピュータのメモリ内のデータであり、同時にこのメモリに対して実行されるアクションを制御します。プログラムを私たちが慣れ親しんでいるオブジェクトに比較しようとするアナロジーは、不足しがちですが、表面的に当てはまるのは機械です。機械式腕時計の歯車は巧みに組み合わされており、時計師が上手であれば、長年にわたって正確に時間を示します。プログラムの要素も同様に組み合わされており、プログラマが自分の仕事を知っていれば、プログラムはクラッシュせずに実行されます。

コンピュータは、これらの非物質的な機械をホストとして機能するように構築された機械です。コンピュータ自体は、愚かで単純な作業しかできません。それらが非常に有用な理由は、これらの作業を信じられないほど高速で実行するためです。プログラムは、これらの単純なアクションを巧みに組み合わせることで、非常に複雑な作業を行うことができます。

私たちの中には、コンピュータプログラムを書くことを魅力的なゲームと考えている人もいます。プログラムは思考の構築物です。構築コストはかからず、重量がなく、私たちのタイピングの手の下で簡単に成長します。もし私たちが熱中しすぎれば、そのサイズと複雑さは制御不能に成長し、それを創造した者でさえ混乱させるでしょう。これがプログラミングの主な問題です。今日のソフトウェアの多くがクラッシュしたり、失敗したり、めちゃくちゃになったりする理由です。

プログラムが動作すると、それは美しいものです。プログラミングの芸術とは、複雑さを制御するスキルです。優れたプログラムは控えめで、その複雑さの中でシンプルになっています。


今日、多くのプログラマは、この複雑さは、プログラム内でよく理解されている少数のテクニックだけを使用することによって最も効果的に管理されると考えています。彼らはプログラムが持つべき形式について厳格なルールを定めており、熱心な人々は、これらのルールを破る者を悪いプログラマとして非難します。

プログラミングの豊かさにどんな敵意でしょう!それを単純で予測可能なものにするために、奇妙で美しいすべてのプログラムにタブーを置くために。プログラミング技法の風景は膨大であり、その多様性において魅力的で、まだ大部分が未開拓です。確かに罠や落とし穴が散らばっており、経験の浅いプログラマをあらゆる種類のひどい間違いに誘いますが、それは慎重に進み、機転を利かせる必要があるという意味だけです。学ぶにつれて、常に新たな課題、新たな領域探検があります。探検をやめるプログラマは間違いなく停滞し、喜びを忘れ、プログラミングする意志を失います(そしてマネージャーになります)。

私に関する限り、プログラムの明確な基準は、それが正しいかどうかです。効率性、明瞭性、サイズは重要ですが、それらをどのようにバランスさせるかは常に判断の問題であり、各プログラマが自分で行わなければならない判断です。経験則は有用ですが、それを破ることを恐れるべきではありません。


計算の始まり、誕生時には、プログラミング言語はありませんでした。プログラムはこんな感じに見えました。

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. メモリ位置0に数値0を格納する
  2. メモリ位置1に数値1を格納する
  3. メモリ位置1の値をメモリ位置2に格納する
  4. メモリ位置2の値を数値11だけ減らす
  5. メモリ位置2の値が数値0の場合、命令9に進みます
  6. メモリ位置0の値にメモリ位置1の値を加算する
  7. メモリ位置1の値に数値1を加算する
  8. 命令3に進みます
  9. メモリ位置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行は、プログラムがまだ11ではないと決定したたびに、結果にcountの値を追加し、countを1ずつ増分します。

これがJavaScriptでの同じプログラムです。

var total = 0, count = 1;
while (count <= 10) {
  total += count;
  count += 1;
}
print(total);

これにより、さらにいくつかの改善が得られます。最も重要なのは、プログラムを行ったり来たりしたい方法を指定する必要がなくなったことです。魔法の言葉whileがそれを処理します。与えられた条件が成り立つ限り、その下の行を実行し続けます。count <= 10は、「countは10以下である」という意味です。明らかに、一時的な値を作成してゼロと比較する必要はもうありません。これは愚かな小さな詳細であり、プログラミング言語のパワーは、私たちのために愚かな小さな詳細を処理することです。

最後に、便利な演算rangesumが利用可能だった場合、プログラムがどのように見えるかを示します。それぞれ、範囲内の数値のコレクションを作成し、数値のコレクションの合計を計算します。

print(sum(range(1, 10)));

したがって、この物語の教訓は、同じプログラムを長くしたり短くしたり、読みづらくしたり読みやすくしたりできるということです。プログラムの最初のバージョンは非常に分かりにくかったのに対し、最後のバージョンはほぼ英語です。1から10までの数値のrangesumprintします。(後続の章で、sumrangeのようなものを作成する方法を示します。)

優れたプログラミング言語は、より抽象的な方法で自分を表現できるようにプログラマを支援します。それは興味のない詳細を隠し、便利な構成要素(while構造など)を提供し、ほとんどの場合、プログラマが自分で構成要素を追加できるようにします(sumrange演算など)。


JavaScriptは、現在、ワールドワイドウェブ上のページで様々な巧妙で厄介なことを行うために最も多く使用されている言語です。一部の人々は、JavaScriptの次期バージョンが他のタスクでも重要な言語になると主張しています。それが実現するかどうかは分かりませんが、プログラミングに興味があるなら、JavaScriptは間違いなく学ぶ価値のある言語です。ウェブプログラミングを多く行わなくても、本書で紹介する驚くべきプログラムは、常にあなたの記憶に残り、あなたを悩ませ、他の言語で書くプログラムに影響を与えるでしょう。

JavaScriptについてひどいことを言う人もいます。これらの多くは真実です。初めてJavaScriptで何かを書く必要があったとき、私はすぐにこの言語を嫌うようになりました。それは私がタイプしたほぼすべてを受け入れましたが、私の意図とは全く異なる方法で解釈しました。これは、私が何をしていたのか全く分からなかったことと大きく関係していますが、実際にはここにも真の問題があります。JavaScriptは許容範囲が異常に広いです。この設計の背後にある考え方は、JavaScriptでのプログラミングを初心者にとって容易にすることでした。実際には、システムがそれらを指摘してくれないため、プログラムのバグを見つけるのが難しくなるだけです。

しかし、この言語の柔軟性もまた利点です。より厳格な言語では不可能な多くの技術の余地があり、JavaScriptの欠点を克服するために使用できます。適切に学習し、しばらく使用した後、私は本当にこの言語を好きになりました。


名前が示唆するように、JavaScriptはJavaというプログラミング言語とはほとんど関係ありません。類似した名前は、優れた判断力ではなく、マーケティング上の考慮事項から付けられました。1995年にNetscapeによってJavaScriptが導入されたとき、Java言語は盛んにマーケティングされ、人気が高まっていました。どうやら、誰かがこのマーケティングに乗ろうとするのは良い考えだと考えたようです。今では、その名前のせいで苦労しています。

JavaScriptに関連するものは、ECMAScriptと呼ばれるものです。Netscape以外のブラウザがJavaScript、またはそれに似たものをサポートし始めると、言語の動作を正確に記述するドキュメントが作成されました。このドキュメントで記述されている言語は、標準化を行った組織にちなんでECMAScriptと呼ばれています。

ECMAScriptは汎用プログラミング言語を記述しており、インターネットブラウザへのこの言語の統合については何も述べていません。JavaScriptは、ECMAScriptとインターネットページやブラウザウィンドウを処理するための追加ツールを組み合わせたものです。

ECMAScriptドキュメントで記述されている言語を使用するソフトウェアは他にもいくつかあります。最も重要なのは、Flashで使用されるActionScript言語がECMAScriptに基づいていることです(ただし、標準に厳密に従っているわけではありません)。Flashは、ウェブページに動きと音をたくさん追加するためのシステムです。Flashムービーの作成を学ぶことになったら、JavaScriptの知識は役立つでしょう。

JavaScriptは進化を続けています。本書が出版されて以来、ECMAScript 5がリリースされました。これはここで説明されているバージョンと互換性がありますが、私たち自身が作成する機能の一部を組み込みメソッドとして追加しています。最新のブラウザは、この拡張されたバージョンのJavaScriptを提供しています。2011年の時点で、「ECMAScript Harmony」という、より根本的な言語拡張が標準化されつつあります。本書で学ぶことがこれらの新しいバージョンによって時代遅れになることを心配する必要はありません。まず第一に、それらは現在の言語の拡張になるため、本書に書かれていることはほとんどすべて有効なままです。


本書のほとんどの章にはかなりの量のコード1が含まれています。私の経験では、コードの読み書きはプログラミング学習の重要な部分です。これらの例をざっと見るのではなく、注意深く読んで理解するようにしてください。最初は遅くて混乱するかもしれませんが、すぐに慣れるでしょう。演習についても同様です。実際に動作するソリューションを作成するまで、理解したと仮定しないでください。

ウェブの仕組み上、人々がウェブページに配置したJavaScriptプログラムを常に確認できます。これは、いくつかの方法を学ぶための良い方法です。ほとんどのウェブプログラマは「プロ」のプログラマではないか、JavaScriptプログラミングをそれほど面白くないと考えて適切に学習したことがないため、このように見つけることができるコードの多くは非常に質が悪いものです。醜いコードや間違ったコードから学習すると、醜さと混乱が自分のコードに広がるため、誰から学ぶか注意してください。


プログラム(例と自分で書いたコードの両方)を試すことができるように、本書ではコンソールと呼ばれるものを使用します。最新のグラフィカルブラウザ(Internet Explorerバージョン6以降、Firefox 1.5以降、Opera 9以降、Safari 3以降、Chrome)を使用している場合、本書のページには画面下部に青みがかったバーが表示されます。このバーの右端にある小さな矢印をクリックしてコンソールを開くことができます。(ブラウザの組み込みコンソールについて話しているわけではないことに注意してください)。

コンソールには3つの重要な要素があります。出力ウィンドウは、エラーメッセージやプログラムが出力するものを表示するために使用されます。その下には、JavaScriptを入力できる行があります。数字を入力してEnterキーを押して、入力した内容を実行してみてください。入力したテキストが意味のあるものを生成した場合、それは出力ウィンドウに表示されます。今度はwrong!と入力して、もう一度Enterキーを押してみてください。出力ウィンドウにエラーメッセージが表示されます。上矢印キーと下矢印キーを使用して、以前に入力したコマンドに戻ることができます。

複数行にまたがり、しばらく保持しておきたいより大きなコードについては、右側のフィールドを使用できます。 「実行」ボタンは、このフィールドに記述されたプログラムを実行するために使用されます。同時に複数のプログラムを開くことができます。「新規」ボタンを使用して、新しい空のバッファを開きます。複数のバッファが開いている場合、「実行」ボタンの横にあるメニューを使用して、表示するバッファを選択できます。「閉じる」ボタンは、予想どおりバッファを閉じます。

本書の例プログラムには常に右上に矢印が付いた小さなボタンがあり、これを使用して実行できます。前に見た例は次のようになります。

var total = 0, count = 1;
while (count <= 10) {
  total += count;
  count += 1;
}
print(total);

矢印をクリックして実行します。プログラムをコンソールにロードするために使用される別のボタンもあります。それを変更して結果を試してみてください。最悪の場合、無限ループを作成することです。無限ループは、たとえばカウント変数に1ではなく0を追加することを選択した場合など、whileの条件がfalseにならない場合に発生します。プログラムは永遠に実行されます。

幸いなことに、ブラウザは内部で実行されているプログラムを監視しています。プログラムの終了に不当に時間がかかると、中断するかどうかを尋ねられます。


後の章では、多くのコードブロックからなる例プログラムを作成します。多くの場合、プログラムを動作させるには、それらのすべてを実行する必要があります。お気づきかもしれませんが、コードブロック内の矢印は、ブロックが実行された後、紫色になります。章を読むときは、特に新しいものを「定義する」コードブロック(次の章で意味が分かります)など、遭遇するすべてのコードブロックを実行してみてください。

もちろん、一度に座って章を読むことができない場合があります。つまり、読み込みを再開するときに途中で始める必要がありますが、章の先頭からすべてのコードを実行しないと、機能しない場合があります。コードブロックの「実行」矢印を押しながらShiftキーを押すと、その前のすべてのブロックも実行されるため、章の途中で始めるときは、最初にコードを実行するときにShiftキーを押すと、すべてが期待どおりに機能します。

  1. 「コード」とは、プログラムを構成する物質です。プログラムの一部分、それが1行であっても全体であっても、「コード」と呼ばれる場合があります。