第3版が利用可能です。こちらで読んでください

第2章
プログラム構造

そして私の心臓は、薄くて透き通る私の皮膚の下で明るい赤色に輝き、彼らは私を戻すために10ccのJavaScriptを投与しなければなりません。(私は血液中の毒素によく反応します。) なんてこった、あの薬物は本当にあなたのエラから桃を蹴り飛ばすだろう!

_why, Why's (Poignant) Guide to Ruby

この章では、実際にプログラミングと呼べることを始めます。これまで見てきた名詞や断片的な文章を超えて、JavaScript言語の理解を深め、意味のある文章を表現できるようになります。

式と文

第1章では、いくつかの値を作成し、演算子を適用して新しい値を取得しました。このような値の作成は、すべてのJavaScriptプログラムにおいて不可欠な部分ですが、それは一部に過ぎません。

値を生成するコードの断片は、と呼ばれます。リテラルで記述されたすべての値(例:22または"psychoanalysis")は式です。括弧で囲まれた式も式であり、2つの式に適用された二項演算子や1つの式に適用された単項演算子も同様です。

これは、言語ベースのインターフェースの美しさの一部を示しています。式は、人間の言語における副文が入れ子になる方法と非常によく似た方法で入れ子にすることができます。副文は独自の副文を含むことができ、以下同様です。これにより、任意の複雑な計算を表すために式を組み合わせることができます。

式が文の断片に対応する場合、JavaScriptのは人間の言語における完全な文に対応します。プログラムは、単に文のリストです。

最も単純な文の種類は、その後にセミコロンが付いた式です。これはプログラムです。

1;
!false;

しかし、これは役に立たないプログラムです。式は、値を生成するだけで満足することができ、その値は包含する式で使用することができます。文はそれ自体で成立し、世界に影響を与える場合にのみ意味を持ちます。画面に何かを表示する(これは世界を変えることに相当します)か、後続の文に影響を与えるような方法でマシンの内部状態を変更することができます。これらの変更は副作用と呼ばれます。前の例における文は、1trueの値を生成するだけで、すぐに破棄します。これは世界に全く印象を与えません。プログラムを実行しても、観測可能な変化は何も起こりません。

場合によっては、JavaScriptでは文の末尾のセミコロンを省略できます。他の場合では、セミコロンが必要であり、そうでないと次の行が同じ文の一部として扱われます。安全に省略できる場合のルールはやや複雑で、エラーが発生しやすいです。この本では、セミコロンが必要な文は常にセミコロンで終了します。少なくともセミコロンの省略に関する微妙な点を理解するまでは、自分のプログラムでも同じことをすることをお勧めします。

変数

プログラムはどのようにして内部状態を維持するのでしょうか?どのようにして物事を覚えるのでしょうか?古い値から新しい値を生成する方法を見てきましたが、これは古い値を変更するものではなく、新しい値はすぐに使用されなければ再び消散します。値を捕捉して保持するために、JavaScriptは変数と呼ばれるものを提供します。

var caught = 5 * 5;

そして、それは私たちの2番目の文の種類を与えてくれます。特別な単語(キーワードvarは、この文が変数を定義しようとしていることを示しています。その後に変数の名前が続き、すぐに値を与えたい場合は、=演算子と式が続きます。

前の文はcaughtという変数を作成し、それを用いて5に5を掛けた結果の数を取得します。

変数が定義された後、その名前を式として使用できます。そのような式の値は、変数が現在保持している値です。例を以下に示します。

var ten = 10;
console.log(ten * ten);
// → 100

変数名は、予約語(例:var)ではない任意の単語にすることができます。スペースを含めることはできません。数字も変数名の一部にすることができます(例:catch22は有効な名前です)。ただし、名前は数字で始めることはできません。変数名は、$_を除く句読点を含めることはできません。

変数が値を指している場合、それがその値に永遠に結び付けられるという意味ではありません。=演算子は、既存の変数に対していつでも使用して、それらを現在の値から切り離し、新しい値を指すようにすることができます。

var mood = "light";
console.log(mood);
// → light
mood = "dark";
console.log(mood);
// → dark

変数を箱ではなく触手として想像する必要があります。それらは値を含むのではなく、つかむのです。2つの変数は同じ値を参照することができます。プログラムは、まだ保持している値のみにアクセスできます。何かを覚える必要がある場合、それを保持するために触手を伸ばすか、既存の触手の1つをそれに再接続します。

Variables as tentacles

例を見てみましょう。ルイージがまだあなたにいくら借りているかを覚えるために、変数を作成します。そして彼が35ドルを返済したとき、この変数に新しい値を与えます。

var luigisDebt = 140;
luigisDebt = luigisDebt - 35;
console.log(luigisDebt);
// → 105

値を与えずに変数を定義する場合、触手はつかむものが何もないため、空中に終わります。空の変数の値を要求すると、undefinedという値が返されます。

単一のvar文では、複数の変数を定義できます。定義はコンマで区切る必要があります。

var one = 1, two = 2;
console.log(one + two);
// → 3

キーワードと予約語

varなどの特別な意味を持つ単語はキーワードであり、変数名としては使用できません。また、将来のバージョンのJavaScriptで「使用のために予約されている」単語がいくつかあります。これらも公式には変数名として使用することは許可されていませんが、一部のJavaScript環境では許可されています。キーワードと予約語の完全なリストはかなり長いです。

break case catch class const continue debugger
default delete do else enum export extends false
finally for function if implements import in
instanceof interface let new null package private
protected public return static super switch this
throw true try typeof var void while with yield

これらを暗記する必要はありませんが、変数の定義が期待通りに動作しない場合、これが問題である可能性があることを覚えておいてください。

環境

特定の時間に存在する変数とその値の集合は、環境と呼ばれます。プログラムが起動すると、この環境は空ではありません。それは常に言語標準の一部である変数を含んでおり、ほとんどの場合、周囲のシステムと対話する方法を提供する変数を含んでいます。たとえば、ブラウザでは、現在ロードされているウェブサイトを検査および操作し、マウスとキーボードの入力を取得するための変数と関数が存在します。

関数

デフォルトの環境で提供される値の多くは、関数という型を持っています。関数は、値にラップされたプログラムの一部です。そのような値は、ラップされたプログラムを実行するために適用することができます。たとえば、ブラウザ環境では、変数alertは、メッセージ付きの小さなダイアログボックスを表示する関数を保持しています。これは次のように使用されます。

alert("Good morning!");
An alert dialog

関数を実行することを、呼び出し実行、または適用といいます。関数の値を生成する式の後に括弧を付けることで、関数を呼び出すことができます。通常、関数を保持する変数の名前を直接使用します。括弧内の値は、関数の内部のプログラムに渡されます。この例では、alert関数は、渡された文字列をダイアログボックスに表示するテキストとして使用します。関数に渡される値は、引数と呼ばれます。alert関数は1つしか必要としませんが、他の関数は異なる数または異なる型の引数が必要となる場合があります。

console.log関数

alert関数は、実験する際の出力デバイスとして役立ちますが、それらの小さなウィンドウをすべて閉じていると、イライラしてきます。以前の例では、値を出力するためにconsole.logを使用しました。ほとんどのJavaScriptシステム(すべての最新のWebブラウザとNode.jsを含む)は、その引数をあるテキスト出力デバイスに書き出すconsole.log関数を提供します。ブラウザでは、出力はJavaScriptコンソールに表示されます。ブラウザインターフェースのこの部分はデフォルトで非表示になっていますが、ほとんどのブラウザではF12キーを押すと(Macの場合はCommand-Option-Iキーを押すと)開きます。それでも機能しない場合は、メニューから「Webコンソール」または「開発者ツール」という項目を探してください。

この本のページで例や独自のコードを実行する場合、console.logの出力はブラウザのJavaScriptコンソールではなく、例の後に出力されます。

var x = 30;
console.log("the value of x is", x);
// → the value of x is 30

変数名にピリオド文字を含めることはできませんが、console.logには明らかにピリオドが含まれています。これは、console.logが単純な変数ではないためです。実際には、console変数が保持する値からlogプロパティを取得する式です。これは第4章で詳しく説明します。

戻り値

ダイアログボックスの表示や画面へのテキスト書き込みは、副作用です。多くの関数は、生成する副作用のために役立ちます。関数も値を生成する場合があり、その場合、有用であるために副作用を持つ必要はありません。たとえば、Math.max関数は任意の数の数値をとり、最大値を返します。

console.log(Math.max(2, 4));
// → 4

関数が値を生成する場合、その値を返すと言われます。値を生成するものはすべてJavaScriptの式であるため、関数呼び出しはより大きな式内で使用できます。ここでは、Math.maxの反対であるMath.minへの呼び出しが、プラス演算子の入力として使用されています。

console.log(Math.min(2, 4) + 100);
// → 102

次の章では、独自の関数の書き方を説明します。

promptとconfirm

ブラウザ環境には、ウィンドウを開くためにalert以外にも関数が含まれています。confirmを使用して、ユーザーにOK/キャンセルを尋ねることができます。これはブール値を返します。ユーザーがOKをクリックするとtrue、キャンセルをクリックするとfalseが返されます。

confirm("Shall we, then?");
A confirm dialog

prompt関数は、「開かれた」質問をするために使用できます。最初の引数は質問で、2番目の引数はユーザーが開始するテキストです。テキスト行をダイアログウィンドウに入力でき、関数はこのテキストを文字列として返します。

prompt("Tell me everything you know.", "...");
An prompt dialog

これらの2つの関数は、最新のWebプログラミングではあまり使用されていません。これは主に、結果のウィンドウの外観を制御できないためですが、おもちゃのプログラムや実験には役立ちます。

制御フロー

プログラムに複数のステートメントが含まれている場合、ステートメントは予測可能な方法で上から下に実行されます。基本的な例として、このプログラムには2つのステートメントがあります。最初のステートメントはユーザーに数値を要求し、2番目のステートメントはその後実行され、その数値の2乗を表示します。

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

Number関数は値を数値に変換します。promptの結果は文字列値であり、数値が必要なため、この変換が必要です。値をこれらの型に変換するStringBooleanという同様の関数があります。

これが、かなり単純な直線的な制御フローの概略図です。

Trivial control flow

条件付き実行

ステートメントを直線的に実行することだけが唯一の選択肢ではありません。別の方法として、条件付き実行があり、ブール値に基づいて2つの異なる経路を選択します。

Conditional control flow

JavaScriptでは、条件付き実行はifキーワードで記述されます。単純なケースでは、特定の条件が満たされた場合にのみ、コードを実行したい場合だけです。たとえば、前のプログラムでは、入力が実際に数値である場合にのみ、入力の2乗を表示したい場合があります。

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

この変更を加えると、「チーズ」と入力した場合、出力は表示されません。

ifキーワードは、ブール式の値に応じて、ステートメントを実行またはスキップします。決定する式は、キーワードの後に括弧で囲んで記述し、その後に実行するステートメントが続きます。

isNaN関数は、標準的なJavaScript関数であり、引数がNaNの場合にのみtrueを返します。Number関数は、有効な数値を表していない文字列を渡すとNaNを返すことがあります。したがって、条件は「theNumberが数値でない場合を除いて、これを実行する」という意味になります。

多くの場合、条件が真である場合に実行されるコードだけでなく、他のケースを処理するコードも必要になります。この代替パスは、図の2番目の矢印で表されます。elseキーワードは、ifと組み合わせて使用して、2つの別々の代替実行パスを作成できます。

var theNumber = Number(prompt("Pick a number", ""));
if (!isNaN(theNumber))
  alert("Your number is the square root of " +
        theNumber * theNumber);
else
  alert("Hey. Why didn't you give me a number?");

3つ以上のパスを選択する必要がある場合は、複数のif/elseのペアを「連鎖」させることができます。例を以下に示します。

var num = Number(prompt("Pick a number", "0"));

if (num < 10)
  alert("Small");
else if (num < 100)
  alert("Medium");
else
  alert("Large");

プログラムはまず、numが10未満かどうかを確認します。10未満の場合、その分岐を選択し、「Small」を表示して終了します。10未満でない場合、else分岐に進みます。それ自体に2番目のifが含まれています。2番目の条件(< 100)が満たされている場合、数値は10〜100の間であり、「Medium」が表示されます。満たされていない場合、2番目かつ最後のelse分岐が選択されます。

このプログラムのフローチャートは次のようになります。

Nested if control flow

whileループとdoループ

0から12までのすべての偶数を印刷するプログラムを考えてみましょう。これを記述する方法は次のとおりです。

console.log(0);
console.log(2);
console.log(4);
console.log(6);
console.log(8);
console.log(10);
console.log(12);

これは機能しますが、プログラムを作成するという考え方は、作業量を減らすことであり、増やすことではありません。1,000未満のすべての偶数が必要な場合、前述の方法は機能しません。必要なのは、コードを繰り返す方法です。この形式の制御フローはループと呼ばれます。

Loop control flow

ループ制御フローを使用すると、以前にいたプログラムのポイントに戻り、現在のプログラムの状態を使用して繰り返すことができます。これをカウントする変数と組み合わせると、次のようなことができます。

var number = 0;
while (number <= 12) {
  console.log(number);
  number = number + 2;
}
// → 0
// → 2
//   … etcetera

whileキーワードで始まるステートメントはループを作成します。whileの後に括弧で囲まれた式が続き、その後にifと同様にステートメントが続きます。ループは、式がブール型に変換されたときにtrueの値を生成する限り、そのステートメントを実行します。

このループでは、現在の数値を印刷し、変数に2を追加する必要があります。ループ内で複数のステートメントを実行する必要があるときはいつでも、中括弧({})で囲みます。中括弧は、式に対して括弧が果たす役割をステートメントに対して果たします。つまり、それらをグループ化して、単一のステートメントとしてカウントします。中括弧で囲まれた一連のステートメントは、ブロックと呼ばれます。

多くのJavaScriptプログラマは、すべてのループまたはifの本体を中括弧で囲みます。これは、一貫性のために、そして後で本体のステートメントの数を変更するときに中括弧を追加または削除する必要がないようにするために行われます。この本では、簡潔さを重視するため、ほとんどの単一ステートメントの本体を中括弧なしで記述します。どちらのスタイルを使用しても構いません。

number変数は、変数がプログラムの進捗状況を追跡する方法を示しています。ループが繰り返されるたびに、number2ずつ増加します。次に、各反復の開始時に、プログラムが意図した作業をすべて完了したかどうかを判断するために、12と比較されます。

実際に何か有用なことを行う例として、210(2の10乗)の値を計算して表示するプログラムを記述できます。結果を追跡する変数と、結果に2を掛けた回数をカウントする変数の2つの変数を使用します。ループは、2番目の変数がまだ10に達したかどうかをテストし、両方の変数を更新します。

var result = 1;
var counter = 0;
while (counter < 10) {
  result = result * 2;
  counter = counter + 1;
}
console.log(result);
// → 1024

カウンターは1から開始して<= 10を確認することもできますが、第4章で明らかになる理由から、0からカウントすることに慣れることをお勧めします。

doループは、whileループと同様の制御構造です。1点だけが異なります。doループは常にその本体を少なくとも1回実行し、最初の実行後にのみ停止するかどうかをテストし始めます。これを反映するために、テストはループの本体の後に出現します。

do {
  var yourName = prompt("Who are you?");
} while (!yourName);
console.log(yourName);

このプログラムは、名前の入力を強制します。空でない文字列になるまで、何度も繰り返し要求します。!演算子を適用すると、値はブール型に変換されてから否定され、""を除くすべての文字列はtrueに変換されます。つまり、空でない文字列を提供するまで、ループは繰り返し実行されます。

コードのインデント

おそらく、いくつかの文の前に空白を入れたことに気づかれたでしょう。JavaScriptでは、これらは必須ではありません。コンピュータは空白なしでもプログラムを受け入れます。実際、プログラムにおける改行もオプションです。必要であれば、プログラムを1行の長い行として記述することもできます。ブロック内のインデントの役割は、コードの構造を際立たせることです。複雑なコードでは、新しいブロックが他のブロック内で開かれるため、あるブロックの終わりと別のブロックの始まりを見分けるのが難しくなる場合があります。適切なインデントを使用すると、プログラムの視覚的な形状が、その内部のブロックの形状に対応します。私は、開いているブロックごとに2つのスペースを使用するのが好きですが、好みは異なります。4つのスペースを使用する人もいれば、タブ文字を使用する人もいます。

forループ

多くのループは、前のwhileの例で見られるパターンに従います。まず、「カウンター」変数が作成され、ループの進行状況を追跡します。次に、whileループがあり、そのテスト式は通常、カウンターがまだ境界に達したかどうかをチェックします。ループ本体の最後に、カウンターが更新されて進捗状況を追跡します。

このパターンは非常に一般的であるため、JavaScriptおよび同様の言語では、より短く、より包括的な形式であるforループが提供されています。

for (var number = 0; number <= 12; number = number + 2)
  console.log(number);
// → 0
// → 2
//   … etcetera

このプログラムは、前の偶数を出力する例と完全に同等です。「状態」に関連するすべての文がまとめてグループ化されている点が異なります。

forキーワードの後の括弧には、2つのセミコロンを含める必要があります。最初のセミコロンの前にある部分は、通常は変数を定義することによってループを初期化します。2番目の部分は、ループを継続する必要があるかどうかをチェックする式です。最後の部分は、各反復後にループの状態を更新します。ほとんどの場合、これはwhile構造よりも短く、明確です。

以下は、whileではなくforを使用して210を計算するコードです。

var result = 1;
for (var counter = 0; counter < 10; counter = counter + 1)
  result = result * 2;
console.log(result);
// → 1024

{でブロックが開かれていない場合でも、ループ内の文は2つのスペースでインデントされ、前の行に「属している」ことが明確になっています。

ループからの脱出

ループの条件がfalseになることが、ループが終了する唯一の方法ではありません。breakと呼ばれる特別な文があり、囲んでいるループからすぐにジャンプアウトする効果があります。

このプログラムは、break文を示しています。20以上で7で割り切れる最初の数値を見つけます。

for (var current = 20; ; current++) {
  if (current % 7 == 0)
    break;
}
console.log(current);
// → 21

剰余(%)演算子を使用すると、ある数値が別の数値で割り切れるかどうかを簡単にテストできます。割り切れる場合、それらの除算の剰余はゼロになります。

例におけるfor構造には、ループの終わりをチェックする部分がありません。これは、内部のbreak文が実行されない限り、ループが決して停止しないことを意味します。

そのbreak文を省略したり、常にtrueを生成する条件を誤って記述したりすると、プログラムは無限ループに陥ります。無限ループに陥ったプログラムは実行を終了しないため、通常は問題となります。

これらのページの例のいずれかで無限ループを作成した場合、通常は数秒後にスクリプトを停止するかどうかを尋ねられます。それでも失敗した場合は、作業中のタブを閉じたり、一部のブラウザではブラウザ全体を閉じたりして復旧する必要があります。

continueキーワードは、ループの進行に影響を与えるという点でbreakに似ています。ループ本体でcontinueが検出されると、制御は本体からジャンプし、ループの次の反復が続行されます。

変数の簡潔な更新

特にループを使用する場合、プログラムは多くの場合、変数の以前の値に基づいて値を保持するように変数を「更新」する必要があります。

counter = counter + 1;

JavaScriptでは、これに対するショートカットを提供しています。

counter += 1;

同様のショートカットは、result *= 2resultを2倍にする、またはcounter -= 1でカウントを減らすなど、他の多くの演算子にも機能します。

これにより、カウントの例をさらに短くすることができます。

for (var number = 0; number <= 12; number += 2)
  console.log(number);

counter += 1counter -= 1には、さらに短い同等物があります。counter++counter--です。

switchによる値のディスパッチ

コードは通常、次のようになります。

if (variable == "value1") action1();
else if (variable == "value2") action2();
else if (variable == "value3") action3();
else defaultAction();

このような「ディスパッチ」をより直接的な方法で解決することを目的としたswitchという構文があります。残念ながら、JavaScriptがこれに対して使用する構文(C/Java系のプログラミング言語から継承されたもの)はややぎこちないため、if文の連鎖の方が多くの場合、見栄えが良いです。例を以下に示します。

switch (prompt("What is the weather like?")) {
  case "rainy":
    console.log("Remember to bring an umbrella.");
    break;
  case "sunny":
    console.log("Dress lightly.");
  case "cloudy":
    console.log("Go outside.");
    break;
  default:
    console.log("Unknown weather type!");
    break;
}

switchで開かれたブロック内には、任意の数のcaseラベルを配置できます。プログラムは、switchに与えられた値に対応するラベル、または一致する値が見つからない場合はdefaultにジャンプします。そして、別のラベルの下にあっても、そこに記述されている文を実行し始め、break文に到達するまで実行を続けます。例では"sunny"の場合のように、いくつかのケースでコードを共有するために使用できます(晴れと曇りの両方で外に出かけることを推奨しています)。しかし注意してください。このようなbreakを忘れると、実行したくないコードが実行されることになります。

大文字と小文字

変数名にはスペースを含めることはできませんが、変数が表すものを明確に記述するために複数の単語を使用することがしばしば役立ちます。複数単語を含む変数名を書くための選択肢は、ほぼ次のとおりです。

fuzzylittleturtle
fuzzy_little_turtle
FuzzyLittleTurtle
fuzzyLittleTurtle

最初のスタイルは読みづらい場合があります。個人的にはアンダースコアの方が見た目がいいと思いますが、少しタイプするのが面倒です。標準的なJavaScript関数、およびほとんどのJavaScriptプログラマーは、一番下のスタイルに従っています。最初の単語を除くすべての単語を大文字にします。このような小さなことに慣れるのは難しくありませんが、命名スタイルが混在したコードは読みづらくなる可能性があるため、この規則に従います。

Number関数など、一部のケースでは、変数の最初の文字も大文字になります。これは、この関数をコンストラクタとしてマークするために実行されました。コンストラクタとは何かについては、第6章で説明します。現時点では、この明らかな一貫性の欠如に悩まされる必要はありません。

コメント

多くの場合、生のコードでは、プログラムが人間の読者に伝えたい情報をすべて伝えることができず、または難解な方法で伝えるため、人々が理解できない場合があります。また、詩的な気分になったり、プログラムの一部として考えを付け加えたい場合もあります。これがコメントの目的です。

コメントは、プログラムの一部であるテキストですが、コンピュータによって完全に無視されます。JavaScriptには、コメントを記述する2つの方法があります。1行のコメントを記述するには、2つのスラッシュ文字(//)と、その後にコメントテキストを使用します。

var accountBalance = calculateBalance(account);
// It's a green hollow where a river sings
accountBalance.adjust();
// Madly catching white tatters in the grass.
var report = new Report();
// Where the sun on the proud mountain rings:
addToReport(accountBalance, report);
// It's a little valley, foaming like light in a glass.

//コメントは行の終わりまでしか有効ではありません。/**/の間のテキストセクションは、改行が含まれていても無視されます。これは、ファイルまたはプログラムのチャンクに関する情報のブロックを追加する場合に役立ちます。

/*
 I first found this number scrawled on the back of one of
 my notebooks a few years ago. Since then, it has often
 dropped by, showing up in phone numbers and the serial
 numbers of products that I've bought. It obviously likes
 me, so I've decided to keep it.
*/
var myNumber = 11213;

要約

プログラムは文で構成され、文自体がさらに文を含むことがあり、文は式を含み、式自体はより小さな式で構成されることを学びました。

文を次々に配置することで、上から下へ実行されるプログラムが作成されます。条件文(ifelseswitch)とループ文(whiledofor)を使用して、制御の流れに乱れを生じさせることができます。

変数はデータを名前付きで保管するために使用でき、プログラムの状態を追跡するのに役立ちます。環境とは、定義されている変数の集合です。JavaScriptシステムは、常に多数の便利な標準変数を環境に配置します。

関数は、プログラムの一部をカプセル化する特別な値です。functionName(argument1, argument2)と記述することで呼び出すことができます。このような関数呼び出しは式であり、値を生成する場合があります。

練習問題

練習問題の解答を試す方法がわからない場合は、はじめにを参照してください。

各練習問題は、問題の説明から始まります。それを読んで、練習問題を解いてみてください。問題が発生した場合は、練習問題の後のヒントを読んでみてください。練習問題の完全な解答はこの本には含まれていませんが、eloquentjavascript.net/codeでオンラインで見つけることができます。練習問題から何かを学ぶためには、練習問題を解いた後、または少なくとも十分に努力して軽い頭痛がするまで取り組んだ後にのみ、解答を見ることをお勧めします。

三角形をループする

以下の三角形を出力するconsole.logへの7回の呼び出しを行うループを作成してください。

#
##
###
####
#####
######
#######

文字列の後に.lengthを記述することで、文字列の長さを確認できることを知っておくと役立つ場合があります。

var abc = "abc";
console.log(abc.length);
// → 3

ほとんどの練習問題には、問題を解くために修正できるコードの一部が含まれています。コードブロックをクリックして編集できることを忘れないでください。

// Your code here.

単純に1から7までの数字を出力するプログラムから始めることができます。これは、この章の前面で紹介されたforループを使用した偶数出力の例を少し修正することで導き出すことができます。

今度は、数字とハッシュ文字の文字列の同等性について考えてみましょう。1から2へは1を加えることで(+= 1)、"#"から"##"へは文字を加えることで(+= "#")移動できます。したがって、あなたの解決策は、数字出力プログラムに非常によく似ているはずです。

FizzBuzz

console.logを使用して、1から100までのすべての数字を出力するプログラムを作成してください。ただし、2つの例外があります。3で割り切れる数字には、数字の代わりに"Fizz"を出力し、5で割り切れる数字(ただし3では割り切れない数字)には、"Buzz"を出力してください。

それが動作したら、プログラムを修正して、3と5の両方で割り切れる数字には"FizzBuzz"を出力してください(そして、それらのいずれか一方のみで割り切れる数字には、引き続き"Fizz"または"Buzz"を出力してください)。

(これは実際には面接の質問であり、プログラマー候補の相当な割合を除外すると主張されています。そのため、あなたがそれを解いたなら、自分を誇りに思っても構いません。)

// Your code here.

数字を処理することは明らかにループの仕事であり、何を印刷するかを選択することは条件付き実行の問題です。数字が別の数字で割り切れるかどうか(剰余がゼロかどうか)をチェックするために、剰余(%)演算子を使用するテクニックを思い出してください。

最初のバージョンでは、すべての数字に3つの可能な結果があるので、if/else if/elseチェーンを作成する必要があります。

プログラムの2番目のバージョンには、簡単な解決策と巧妙な解決策があります。単純な方法は、与えられた条件を正確にテストするために別の「分岐」を追加することです。巧妙な方法では、出力する単語を含む文字列を作成し、単語がない場合はこの単語または数字を出力します。||演算子を巧みに使用することで実現できます。

チェス盤

改行文字を使用して行を区切る8×8グリッドを表す文字列を作成するプログラムを作成してください。グリッドの各位置には、スペースまたは「#」文字のいずれかがあります。文字はチェス盤を形成する必要があります。

この文字列をconsole.logに渡すと、次のようなものが表示されます。

 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #

このパターンを生成するプログラムができたら、変数size = 8を定義し、プログラムを変更して任意のsizeで動作するようにし、指定された幅と高さのグリッドを出力してください。

// Your code here.

文字列は、空の文字列("")から始めて、繰り返し文字を追加することで構築できます。改行文字は"\n"と記述します。

console.logを使用して、プログラムの出力を確認してください。

2次元で作業するには、ループの中にループが必要です。開始位置と終了位置がわかりやすいように、両方のループの本体を波括弧で囲んでください。これらの本体を適切にインデントしてください。ループの順序は、文字列を作成する順序(行ごと、左から右、上から下)に従う必要があります。そのため、外側のループは行を処理し、内側のループはその行の文字を処理します。

進捗状況を追跡するために2つの変数が必要です。特定の位置にスペースまたはハッシュ記号を配置するかどうかを知るには、2つのカウンターの合計が偶数かどうか(% 2)をテストできます。

改行文字を追加して行を終了する処理は、行が構築された後に行われるため、内側のループの後、外側のループ内で行います。