【Eloquent JavaScript和訳】 Chapter 2: JavaScript の基礎: 値、変数、制御フロー

EloquentJavaScriptJa

公開:

2 なるほど
8,655 VIEW
0 コメント

var luigiDebt = 140;

そして Luigi が返済するたびに、この変数に新しい数字を与えて負債額が減っていきます:

luigiDebt = luigiDebt - 35;

ある時点での変数とその値の集合を 環境 と呼びます。プログラムの開始時、この環境は空です。環境には常に複数の標準変数が含まれます。ブラウザーがページをロードすると、新しい環境が作られ、標準値がそれにアタッチされます。プログラムによって作られ修正される変数は、ブラウザーが新しいページに行くまで存続します。

標準環境で提供される値の多くがタイプ '関数' を持ちます。関数は値にラップされたプログラムの一部です。一般的に、プログラムのこの部分は有益なことを行い、関数値を使って呼び出すことができます。ブラウザー環境では変数 alert がダイアログボックスにメッセージを表示する関数を持っています。次のように使います:

alert("Also, your hair is on fire.");

関数内のコードを実行することを 呼び出し または 適用 と呼びます。これを行う表記法には括弧が使われます。関数値を生み出す式は全て後ろに括弧を置いて呼び出すことができます。括弧で囲まれた文字列値は関数に与えられ、関数はそれをテキストのように使ってダイアログボックスに表示します。関数に与えられる値を パラメーター または 引数 と呼びます。alert が必要とする値は 1 つだけですが、他の関数は複数の値を必要とする場合があります。

ダイアログボックスを表示するのは副作用です。関数の多くは副作用を生みます。関数が値を生み出すことも可能ですが、この場合関数は副作用を持つ必要はありません。例えば、関数 Math.max は 2 つの引数を取り、大きいほうを返します:

alert(Math.max(2, 4));

関数が値を生み出すとき、それは 返す と言われます。JavaScript では値を生み出すものは常に式であるため、関数呼び出しはより多きな式の一部として使うことができます:

alert(Math.min(2, 4) + 100);

3 章で関数の書き方を説明します。

上の例が示すように、alert は式の結果を表示するために使うことができます。しかしわざわざクリックしてこの小さなウィンドウを閉じるのにはイライラします。そこでこれからは alert に似た関数 print を使うことにします。この関数はポップアップ・ウィンドウを開かず、値をコンソールの出力領域に表示します。print は JavaScript の標準関数ではなく、ブラウザーが提供する関数でもありません。しかし本書では使えるようにしました。

print("N");

よく似た関数 show も本書で使えます。print はその引数をフラット・テキストとして表示しますが、show はプログラムでそれが見えるように表示します。このため、値のタイプについてより多くの情報が得られます。例えば、文字列値を show に与える時は引用符が付いたままです:

show("N");

ブラウザーが提供する標準環境にはポップアップ・ウィンドウを開く関数があといくつかあります。confirm を使うとユーザーに OK/Cancel と回答する質問を作ることができます。この関数はユーザーが 'OK' を押した場合は true を、'Cancel' を押した場合は false を返します。

show(confirm("Shall we, then?"));

prompt は '自由な' 回答ができる質問を作ることができます。最初の引数は質問で、2 番目の引数はユーザーが答えるテキストです。1 行分のテキストがウィンドウにタイプでき、関数はこれを文字列として返します。

show(prompt("Tell us everything you know.", "..."));

この環境でほとんど全ての引数に新しい値を与えることができます。これは便利なことですが、危険でもあります。print に値 8 を与えると、それ以上表示することができなくなります。幸運にもコンソールには大きな 'Reset' ボタンがあり、これを押すと環境は元の状態にリセットされます。

1 行プログラムはさほど興味深くはありません。プログラムに複数のステートメントを置くと、ステートメントは予想通り上から下に 1 度に 1 つづつ順番に実行されます。

var theNumber = Number(prompt("Pick a number", ""));
print("Your number is the square root of " +
(theNumber * theNumber));

関数 Number は値を数字に変換します。上記の場合は prompt の結果が文字列値なので必要です。似た関数に String と Boolean があり、値をそれぞれのタイプに変換します。

0 から 12 までの全ての偶数を表示するプログラムを考えてください。一つの方法としては:

print(0);
print(2);
print(4);
print(6);
print(8);
print(10);
print(12);

これでも良いのですが、プログラムを書く目的は仕事量を 減らし、多くしないことです。1000 以下の偶数を全て表示する場合、上記の例は役に立ちません。必要なのは、コードを自動的に繰り返す方法です。

var currentNumber = 0;
while (currentNumber <= 12) {
print(currentNumber);
currentNumber = currentNumber + 2;
}

「はじめに」で while を目にしたかもしれません。ワード while で始まるステートメントはループを作ります。ループはステートメントの並びを変え、プログラムに複数のステートメントを複数回繰り返させます。この場合、ワード while の後には括弧で囲まれた (ここでは括弧は必須です) 式が続き、ループを終わらせるかどうかを決定します。この式のブール値が true である限り、ループ内のコードは繰り返されます。この値が false になると、プログラムはループに最後に行き、通常通りに処理を続けます。

変数 currentNumber は、変数がどのようにプログラムの進捗状況を追跡するかを示してくれます。ループが繰り返されるたびに 2 が加算され、繰り返しの初めで 12 と比較してループを続けるかを決めます。

while ステートメントの 3 番目の部分は別のステートメントです。これはループの本体で、複数回繰り返される処理です。もし数字を表示する必要がないなら、プログラムは次のようになったでしょう:

var currentNumber = 0;
while (currentNumber <= 12)
currentNumber = currentNumber + 2;

ここで currentNumber = currentNumber + 2; はループの本体となるステートメントです。しかし数字も表示しなければならないので、ループ・ステートメントには複数のステートメントが必要です。中括弧 ({ と }) を使ってステートメントを ブロックにグループ化します。ブロックの外では、ブロックが 1 つのステートメントと見なされます。前の例では、ブロックを使って print 呼び出しと currentNumber を更新するステートメントの両方をループに含めました。

Ex. 2.2

これまでのテクニックを使って値 2^10 (2 の 10 乗) を計算して表示するプログラムを書いてください。2 * 2 * ... のような手っ取り早い方法でもかまいません。

これが厄介なら、偶数の例を思い出してください。プログラムは一つの処理を何度か行わなければなりません。while ループのカウンター変数が役立ちます。カウンターを表示する代わりに、プログラムは何かを 2 倍しなければなりません。この何かがもう一つの変数で、ここに結果の値が作られます。

これがどうなるかまだ分からなくても心配ありません。たとえ本章のテクニックを全て完璧に理解していても、それを特定の問題に適用するのは難しいでしょう。コードを読んで書いてみることが助けになります。この回答を検討して次の問題を解いてください。

var result = 1;
var counter = 0;
while (counter < 10) {
result = result * 2;
counter = counter + 1;
}
show(result);

カウンターも 1 から始めて <= 10 をチェックしますが、後で分かるように、0 からカウントを始めることに慣れたほうが良いでしょう。

あなたの回答が私のと全く同じである必要はありません。結果は同じはずです。しかし回答がかなり違っていても、必ず私の回答も理解してください。

Ex. 2.3

前の練習問題の回答に少し修正を加えて、三角形を描くことができます。'三角形を描く' とはテキストを '一見三角形に見えるように表示する' という意味です。

10 行表示してください。最初の行には '#' を 1 つ、次の行には 2 つ、という具合です。

どうやったら X 個の '#' を持つ文字列にできるでしょう? 一つの方法として、必要な時に '内部ループ'、つまりループに中のループ、を使うやり方です。前の繰り返しで使った文字列を再利用し、それに 1 文字加えるとより簡単になります。

var line = "";
var counter = 0;
while (counter < 10) {
line = line + "#";
print(line);
counter = counter + 1;
}

いくつかのステートメントの前にスペースが置かれていることにお気付きでしょう。これらは必須ではありません: コンピュータはスペース無しでもコードを受け付けます。事実、プログラム中での改行も任意です。1 つの長い行で書いてもかまいません。インデントの役目はコードの構造をブロックに分けて読み手に分かりやすくすることです。ブロックの中に別のブロックが展開するため、複雑なコードではブロックが何処で終わり次のブロックが何処から始まるかが分からなくなることがあります。行をインデントするのは、プログラムの内側のブロック見た目に解りやすくするためです。私はブロックの前にスペースを 2 つ置くのが好きですが、これは好みの問題です。

Opera 以外のブラウザーでは、プログラムをタイプするとコンソール内のフィールドに自動的にスペースが入ります。最初は気になりますが、コードをたくさん書いているうちにこれがかなりの時間の節約になることが分かります。Tab キーを押すと、カーソルの現在位置よりもさらにインデントされます。

JavaScript ではステートメントの後のセミコロンを省略できる場合と、それが無いと奇妙なことが起こる場合があります。いつセミコロンを省略しても安全かのルールは複雑で一概に言うことはできません。本書ではどんなセミコロンも省略していません。プログラムを書く際にはこれを強くお勧めします。

これまで見てきた while の使い方は同じパターンを示しています。まず 'counter' 変数が作られます。この変数はループの進行状況を監視します。while 自身がカウンターが限度に来たかをチェックします。そしてループ本体の終わりでカウンターは更新されます。

多くのループがこのパターンです。このため、JavaScript やこれに似た言語はより短くより分かりやすいフォームも提供しています:

for (var number = 0; number <= 12; number = number + 2)
show(number);

このプログラムは前の偶数を表示する例と全く同じ機能です。唯一の違いは、ループの '状態' に関係するステートメントが全て 1 行に収まっていることです。for の後の括弧内にはセミコロンが 2 つ必要です。最初のセミコロンの前の部分でループを 初期化 します。変数を定義することによってこれを行うのが普通です。2 番目の部分はループを続けるべきかを チェック する式です。最後の部分はループの状態を 更新 します。多くの場合、この方が while 構造よりも短く明快です。

これまで変数名でおかしな 大文字 の使い方をしてきました。これらの名前にスペースを使うことができない ― コンピューターが複数の変数と見なす ― ため、名前の選択は多かれ大体次の選択肢しかありません:
fuzzylittleturtle、fuzzy_little_turtle、FuzzyLittleTurtle、または fuzzyLittleTurtle のいずれかです。最初のは読みづらく、個人的には、少々タイプしづらいのですが、下線が付いたものが好きです。しかし、標準の JavaScript 関数や多くの JavaScript プログラマーは最後の例を使います。このようなことに慣れるのはさほど大変ではないので、多数派に従い、最初の語の後の最初を大文字にします。

小数例ですが、Number 関数のように変数の最初を大文字にする場合もあります。これはこの関数をコンストラクターにするためです。コンストラクターについては 8 章 でお話します。差し当たり、この一貫性の無さについては気にしないでください。

var、while、および for のような特別な意味を持つ名前は変数名として使うことは許されません。これらは キーワード と呼ばれます。JavaScript の今後のバージョンで使うために '予約' されている ワード もたくさんあります。いくつかのブラウザーを除き、これらは公式に使用を禁じられています。かなり長いですが以下がそのリストです:

abstract boolean break byte case catch char class const continue
debugger default delete do double else enum export extends false
final finally float for function goto if implements import in
instanceof int interface long native new null package private
protected public return short static super switch synchronized
this throw throws transient true try typeof var void volatile
while with

最終更新:

コメント(0

あなたもコメントしてみませんか?

すでにアカウントをお持ちの方はログイン