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

第2章プログラム構造

そして私の心は、薄く透き通る肌の下で鮮やかな赤に輝き、私を呼び戻すには10ccのJavaScriptを投与する必要があるのです。(私は血液中の毒素によく反応します。)なんてこった、あれは本当に鰓から桃を叩き出すぞ!

_why, Why's (Poignant) Guide to Ruby
Picture of tentacles holding objects

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

式と文

第1章では、値を作成し、演算子を適用して新しい値を取得しました。このように値を作成することは、あらゆるJavaScriptプログラムの中核を成します。しかし、その中核は、有用になるためにはより大きな構造の中に組み込まれなければなりません。そこで、次にそれを取り上げます。

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

これは、言語ベースのインターフェースの美しさの一部を示しています。式は、人間の言語における副文が入れ子になっているのと同様に、他の式を含むことができます。副文は独自の副文を含むことができ、以下同様です。これにより、任意の複雑な計算を記述する式を構築できます。

式が文の断片に対応するならば、JavaScriptのは完全な文に対応します。プログラムは文のリストです。

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

1;
!false;

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

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

バインディング

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

let caught = 5 * 5;

これは2番目の文の種類です。特別な単語(キーワードletは、この文がバインディングを定義しようとしていることを示しています。その後にバインディングの名前が続き、すぐに値を与えたい場合は、=演算子と式が続きます。

前の文はcaughtというバインディングを作成し、それを用いて5に5を掛け算して生成された数値を保持します。

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

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

バインディングが値を指している場合、それがその値に永久的に結び付けられているわけではありません。=演算子は、既存のバインディングに対していつでも使用して、現在の値との接続を解除し、新しい値を指すようにすることができます。

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

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

別の例を見てみましょう。ルイージがまだあなたにいくら借金しているかを覚えるために、バインディングを作成します。そして、彼が35ドルを返済したら、このバインディングに新しい値を与えます。

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

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

単一のlet文で複数のバインディングを定義できます。定義はコンマで区切る必要があります。

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

varconstという単語も、letと同様にバインディングを作成するために使用できます。

var name = "Ayda";
const greeting = "Hello ";
console.log(greeting + name);
// → Hello Ayda

最初のvar(「variable」の略)は、2015年以前のJavaScriptでバインディングを宣言する方法でした。次の章で、letとどのように異なるかを詳しく説明します。今のところ、それはほとんど同じことをしますが、混乱を招く特性があるため、この本ではほとんど使用しないことを覚えておいてください。

constという単語は定数を表します。これは、存続する限り同じ値を指す定数バインディングを定義します。これは、後で簡単に参照できるように値に名前を与えるバインディングに役立ちます。

バインディング名

バインディング名は任意の単語にすることができます。数字はバインディング名の一部にすることができます(例:catch22は有効な名前です)。ただし、名前は数字で始めることはできません。バインディング名にはドル記号($)またはアンダースコア(_)を含めることができますが、他の句読点や特殊文字は含めることはできません。

letなどの特別な意味を持つ単語はキーワードであり、バインディング名として使用することはできません。「将来のJavaScriptバージョンで使用するために予約されている」単語もいくつかあり、バインディング名として使用することはできません。キーワードと予約語の完全なリストは非常に長いです。

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

このリストを暗記する必要はありません。バインディングの作成で予期せぬ構文エラーが発生した場合は、予約語を定義しようとしているかどうかを確認してください。

環境

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

関数

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

prompt("Enter passcode");
A prompt dialog

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

prompt関数は、現代のWebプログラミングではあまり使用されません。主に、結果のダイアログの外観を制御できないためですが、簡単なプログラムや実験には役立ちます。

console.log関数

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

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

let 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への呼び出しが、プラス式の1部として使用されています。

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

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

制御フロー

プログラムに複数の文が含まれている場合、文は上から下へとストーリーのように実行されます。このプログラムの例には2つの文があります。最初の文はユーザーに数値を要求し、2番目の文は最初の文の後で実行され、その数値の2乗を表示します。

let theNumber = Number(prompt("Pick a number"));
console.log("Your number is the square root of " +
            theNumber * theNumber);

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

ここに、直線的な制御フローの非常に単純な概略図を示します。

Trivial control flow

条件付き実行

すべてのプログラムが一直線ではありません。たとえば、状況に応じて適切な分岐をとる分岐路を作成したい場合があります。これは条件付き実行と呼ばれます。

Conditional control flow

JavaScriptでは、ifキーワードを使用して条件付き実行を作成します。単純なケースでは、特定の条件が成立する場合に限り、いくつかのコードを実行したい場合があります。たとえば、入力数値が実際に数値である場合にのみ、入力の2乗を表示したい場合があります。

let theNumber = Number(prompt("Pick a number"));
if (!Number.isNaN(theNumber)) {
  console.log("Your number is the square root of " +
              theNumber * theNumber);
}

この変更を加えると、「parrot」と入力した場合、何も出力されません。

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

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

この例では、ifの後の文は中括弧({})で囲まれています。中括弧を使用して、任意の数の文を単一の文(ブロックと呼ばれる)にまとめることができます。この場合、単一の文しか含まれていないため、中括弧を省略することもできますが、必要かどうかを考えなくても済むように、ほとんどのJavaScriptプログラマはこれのようにすべての囲まれた文で中括弧を使用します。この本では、時折1行の文を除いて、主にその規則に従います。

if (1 + 1 == 2) console.log("It's true");
// → It's true

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

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

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

let num = Number(prompt("Pick a number"));

if (num < 10) {
  console.log("Small");
} else if (num < 100) {
  console.log("Medium");
} else {
  console.log("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

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

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

whileキーワードで始まる文はループを作成します。whileの後に括弧で囲まれた式と文が続きます。これはifと非常によく似ています。ループは、式がブール値に変換されたときにtrueの値を生成する限り、その文に継続して入ります。

numberバインディングは、バインディングがプログラムの進捗状況を追跡する方法を示しています。ループが繰り返されるたびに、numberは以前の値より2大きい値を取得します。各繰り返し開始時に、12と比較して、プログラムの作業が完了したかどうかを判断します。

実際に何か便利なことを行う例として、210(2の10乗)の値を計算して表示するプログラムを作成できます。2つのバインディングを使用します。1つは結果を追跡し、もう1つは結果に2を何回掛けたかをカウントします。ループは、2番目のバインディングがまだ10に達したかどうかをテストし、達していない場合は両方のバインディングを更新します。

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

カウンターは1から始めて<= 10をチェックすることもできますが、第4章で明らかになる理由から、0からカウントすることに慣れるのが良いでしょう。

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

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

このプログラムは、名前の入力を強制します。空ではない文字列を取得するまで、繰り返し要求します。!演算子を適用すると、値はブール型に変換されてから否定され、""以外のすべての文字列はtrueに変換されます。これは、空ではない名前を提供するまでループが継続することを意味します。

コードのインデント

例では、より大きな文の一部である文の前にスペースを追加してきました。これらのスペースは必須ではありません。コンピュータはスペースなしでもプログラムを受け入れます。実際、プログラムの改行もオプションです。必要であれば、プログラムを1行の長い行として記述することもできます。

ブロック内のインデントの役割は、コードの構造を際立たせることです。他のブロックの中に新しいブロックが開かれるコードでは、どのブロックが終わり、どのブロックが始まるのかが見にくくなることがあります。適切なインデントを使用すると、プログラムの視覚的な形状が、その内部のブロックの形状に対応します。私は、開いたブロックごとに2つのスペースを使用しますが、好みは分かれます。4つのスペースを使用する人もいれば、タブ文字を使用する人もいます。重要なのは、新しいブロックごとに同じ量のスペースを追加することです。

if (false != true) {
  console.log("That makes sense.");
  if (1 < 2) {
    console.log("No surprise there.");
  }
}

ほとんどのコードエディタプログラム(この本のものも含む)は、新しい行を適切な量だけ自動的にインデントすることで役立ちます。

forループ

多くのループは、`while`の例で示されているパターンに従います。まず、ループの進捗状況を追跡するための「カウンター」バインディングが作成されます。次に`while`ループが続き、通常はカウンターが終了値に達したかどうかをチェックするテスト式が含まれます。ループ本体の最後に、カウンターが更新されて進捗状況を追跡します。

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

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

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

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

これは`while`ではなく`for`を使用して210を計算するコードです。

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

ループからの脱出

ループ条件が`false`になることが、ループが終了する唯一の方法ではありません。`break`という特別なステートメントがあり、これは直ちに囲んでいるループからジャンプする効果があります。

このプログラムは`break`ステートメントを示しています。20以上で7で割り切れる最初の数値を見つけます。

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

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

例にある`for`構造には、ループの終わりをチェックする部分がありません。つまり、内部の`break`ステートメントが実行されない限り、ループは決して停止しません。

その`break`ステートメントを削除した場合、または常に`true`を生成する終了条件を誤って記述した場合、プログラムは*無限ループ*に陥ります。無限ループに陥ったプログラムは実行を完了せず、これは通常悪いことです。

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

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

バインディングを簡潔に更新する

特にループ処理を行う場合、プログラムは、そのバインディングの以前の値に基づいて値を保持するためにバインディングを「更新」する必要があることがよくあります。

counter = counter + 1;

JavaScriptでは、これに対するショートカットが用意されています。

counter += 1;

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

これにより、カウントの例をもう少し短くすることができます。

for (let number = 0; number <= 12; number += 2) {
  console.log(number);
}

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

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

コードは、このような見た目になることは珍しくありません。

if (x == "value1") action1();
else if (x == "value2") action2();
else if (x == "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つのスラッシュ文字(`//`)を使用し、その後にコメントテキストを記述します。

let accountBalance = calculateBalance(account);
// It's a green hollow where a river sings
accountBalance.adjust();
// Madly catching white tatters in the grass.
let 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 an old
  notebook. 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.
*/
const myNumber = 11213;

概要

プログラムはステートメントで構成されており、ステートメント自体にはさらに多くのステートメントが含まれていることを学びました。ステートメントには式が含まれる傾向があり、式自体はより小さな式から構築できます。

ステートメントを次々に配置すると、上から下に実行されるプログラムが作成されます。条件付き(`if`、`else`、`switch`)およびループ(`while`、`do`、`for`)ステートメントを使用して、制御フローの乱れを導入できます。

バインディングを使用して、名前の下にデータの一部を保存でき、プログラムの状態を追跡するのに役立ちます。環境とは、定義されているバインディングのセットです。JavaScriptシステムは、常に多くの便利な標準バインディングを環境に配置します。

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

練習問題

練習問題の解答のテスト方法が不明な場合は、はじめにを参照してください。

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

三角形をループする

次の三角形を出力するために、console.logを7回呼び出すループを作成します。

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

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

let 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"と記述します。

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

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

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