Top▲

JavaScriptで学ぶ 文系の人にもわかるプログラミング入門

第4章   条件分岐

前の章では, いくつかの方法でダイアログボックスを表示してみました。 プログラムとしては, 2, 3行程度のごく短いものでした。 この章から少しずつ複雑な手法を学んでいきましょう。 この章から登場する, 「条件分岐」「繰り返し」などは, どのプログラミング言語にもある非常に基本的な概念です。

条件により処理を変える ── if文

第3章の例をもう少しおもしろくしてみましょう。 最初は英語で「Hello!」と表示しましたが, 今度は日本語にしてみます。 英語だといつもHi!とかHello!ですんで便利ですが, 日本語は, 時刻によってあいさつを変えるので, 次のようにダイアログボックスのメッセージを変えましょう。

ダイアログボックスにメッセージを表示するには, 前に使った関数alert()を使えばよいでしょう。 現在の時刻を見て, それに従ってalert()に渡す引数を変えて呼び出せばよいわけです。 ページが表示される時に, onload()で呼び出すことにして, 同じ関数sayHello()の定義だけを書き換えます。

メモ

sayHello()という名前を付けた関数はいつもまったく同じ働きをしなければいけない, ということはありません。 名前を同じにして機能を変更(追加)していってもよいし, 途中で名前を変えてもかまいません。 ただし, 「名は体を表す」ようにしておかないと, 後で読んだときに他人だけでなく自分も混乱します。 その関数の機能が変わってしまったら名前も変えるのが原則です。 また, 関数の名前を変えたときは, タグの属性onloadの値も同じように変更することをお忘れなく。

プログラム4-1 example04-01.html メッセージを日本語に

前のプログラムと違っているのは, sayHello()の定義だけなので, この中だけ説明しましょう。 まず, 最初の2行。

var today; // 日付に関する「オブジェクト」を保持する変数todayを宣言
var hour; // 時刻を保持する変数hourを宣言

この2行はいずれも「変数」を「宣言」している「文」です。 変数をどう使うか徐々に説明していきますが, 「このプログラムでは, todayとhourという変数を使いますよ」とここで宣言しています。 varはvariable(変数)を省略したもので, 「予約語(reserved word)」と呼ばれるJavaScriptプログラムで特別な役目をする単語です。

メモ

なぜ変数を宣言するかと言うと, まずプログラムを読む人に, 「このプログラムではtodayとhourという変数を使いますよ。 覚えておいてください」と伝えるためです。 同時に, プログラムを実行してくれるJavaScriptの「処理系」に対して, 「このプログラムではtodayとhourという変数を使うので, そのための場所を用意しておいてください」と伝える役目もします。

じつはJavaScript(や一部の言語)では, 変数は宣言せずに使ってもかまいません。 JavaScriptはどちらかというと, 気軽に小さなプログラムを作って実行してみようという雰囲気の言語なので, これらの言語を設計した人はいちいち変数の宣言はしなくてもよいことにしたわけです。

これに対して, C, C++, Javaなど, 他の多くの言語では使用する変数は必ず宣言します。 なぜ面倒なことをあえてやるのかというと, 変数を宣言することによりエラーを未然に防げるのです。 たとえば, 宣言することにより変数の入力ミスなどを比較的簡単に見つけられます。 上のプログラムの12行目でhourをourと間違えて入力してしまっても, JavaScriptではエラーにならず実行できてしまいまい, ourには時刻ではなく(自動的に)0が入るためプログラムがおかしな動作をしてしまいます。 これに対して, Javaなどの言語では, ourと書いてあると「宣言されていない変数が使われている」というエラーが出てプログラムは実行できません。

簡便さを優先するか, エラーを未然に防ぐ方を優先するか, 言語によってその設計思想が違っているわけで, どちらがありがたいか, 一概には言えません。 用途によってどちらの言語を使うかを考えて使うのがよいでしょう。

メモ

ES2015という新しいJavaScriptのバージョンでは, 変数の宣言にvarの代わりにletというキーワードが使えるようになっています。 将来的にはletを使うほうがおすすめですが, まだ古いブラウザではletを使うとエラーになってしまうため, このコラムでは(しばらくは)varを使う方法を紹介しておきます。

では, 次の行。

today = new Date();  // Dateオブジェクトを作りtodayに「代入」

new Date()によって, Dateという日付に関するさまざまな情報を保持している「オブジェクト」が生成され, そのオブジェクトが変数todayに「代入(assign)」されて記憶されます。 オブジェクトとはいったい何か? を説明するのにはかなりのスペースが必要ですから, これはもう少しプログラミングについていろいろな知識を身につけてからにしましょう。 ここでは, このように利用できるのだと覚えておいてください。

メモ

日常生活においてもそうだと思いますが, プログラミングを学ぶ際にも, 細かいことは置いておいて当面無条件で覚えた方が楽なことがあります。 そういったことをいちいち突き詰めていると, まったく先に進めなくなる場合もあるので, いったん「棚上げ」して, 後で棚から下ろして解決するという姿勢も必要です。

ただ, 何から何まで棚上げしていては, これまたまったく知識が付かないので程度問題ではあるのですが…。 ここでは「オブジェクトとはいったい何なのか」「その定義は?」といったことはいったん棚上げして, 単にDateを使えば, どのようなことができるのか「雰囲気をつかむ」ことに集中してください。

変数に何かを「代入」するというのは, その変数用に用意されている領域(メモリ)にその何かを保存しておくことを言います。 たとえば, 上の例ではnew Date()によって生成されたDateオブジェクトを扱うのに必要な情報が, todayという名前が付けられた場所に記憶されます。

次の行は, todayに代入されたDateオブジェクトを活用した例です。

hour = today.getHours();  // todayから時刻を取り出してhourに代入

todayにはDateオブジェクトが記憶されているわけですが, Dateオブジェクトには, getHours()という関数(メソッド)が用意されています。 today.getHours()で, 現在の時刻(24時間制)を取り出して返してくれます。 したがって, たとえば, 午後1時7分25秒にこのHTMLページをブラウザに読み込んでこのプログラムを実行したとすれば, today.getHours()からは13が戻ってきて, この値が変数hourに記憶されることになります。 ちなみにtoday.getMinutes(), today.getSeconds()なども用意されていて, それぞれ7, 25が戻ってきます。 さらに, 年や月を得るためにtoday.getFullYear(), today.getMonth()なども利用可能です。

メモ

代入は「=」を使って表しますが, この「=」は, プログラミング以外の「普通の世界」での使われ方とは違っています。 普通の「=」は, 左辺と右辺が等しいことを表します(たとえば, 19-3 = 16)。 しかし, JavaScriptの「=」は代入を表すもので, 右辺で計算した結果(や右辺でできたオブジェクトなど)を, 左辺の表す場所に記憶するという意味を表すのです。

次の文を見てください。

  x = 3;

JavaScriptでは, これはxが3である(3と等しい)ことを表しているのではなく, 3という値がxという名前を付けられた場所に記憶されるということを表しています。 気持ちとしては, 次のような表記のほうがピッタリでしょう。

  x ← 3;

メモ

上で見たプログラムでは文の最後に「;」(セミコロン)がついていますが, JavaScriptではこの「;」を省略することができます。 つまり, 次のように書いてもOKです。

  hour = today.getHours()  // 最後に「;」がない

ただし, 次のように, 同じ行に複数の文を書くときは, 間に「;」を入れて, 区切りを明示する必要があります。

  today = new Date();   hour = today.getHours()

1行にいくつの文を書いてもよいのですが, 普通はせいぜい2文くらいしか書きません。 このときの「行」とは改行文字(Enterあるいはreturnのキーを入力したときに入る文字)によって区切られた「行」を言います。 エディタやワープロソフトで折り返されて2つの「行」にわたって表示されていても改行文字が入っていなければ, プログラムでは1「行」として扱います。 プログラムの処理系(インタプリタやコンパイラ)は改行文字までをひとつの単位として処理します。

1行にいくつ文を書いてもよいのですが, 逆に複数行を使って1文を記述してもかまいません。 たとえば, 次のように書いてもJavaScriptの処理系は2行まとめて1文として解釈してくれるため, エラーにはなりません。

  today =
         new Date();   

ただし, このように1行で問題なく書けてしまう文をあえて2行にするのは, 読みにくくなるので実際にはやめた方がよいでしょう。 長い文字列をつなげたりするような場合や, if文などでいろいろな条件を組み合わせて指定する場合は複数行に分けて書いた方がわかりやすくなります(後のほうの例で出てきます)。

なお, JavaScript以外の多くのプログラミング言語では, 文の最後の「;」は, たとえ1行に1文しか書かれていなくても省略はできません。 このコラムでは, ほかの言語も学ぶことを考慮して, 「;」を省略しないで書くことにします。

プログラム4-1のif文の前にあき(空行)があるのは, この上とこの下で処理の内容が分かれるという区切りの意味です。 このように, いろいろな工夫をしてプログラムの内容を把握しやすくすることはとても大切です。

さて, 次がこのプログラムのとなる部分です。

    if (4 <= hour && hour < 10) {  // 午前4時以降10時前まで
        alert("おはようございます。 ");
    }
    else if (10 <= hour && hour < 19) {  // 午前10時以降午後7時前まで
        alert("こんにちは。 ");
    }
    else { // その他の場合。 つまり, 午後7時以降, 翌朝7時前まで
        alert("こんばんは。 ");
    }

ifは, 「もし〜ならば」という意味ですから, 「if (4 <= hour && hour < 10)」で, 「もしhourが4以上で」&&「hourが10より小さい」という条件が満たされれば, ということになります。 「<=」は「≦」の意味なのですが, 英語などで普通に使われるキーボードでは「≦」は入力できないので, 代わりに「<=」と書きます。 「&&」は「かつ」を意味する記号でand(アンド)と読みます。 まとめると「もしhourが4以上で, かつ, hourが10より小さい場合」に, その下の行, つまり次を実行することになります。

alert("おはようございます。 ");

elseは, 「でなければ」という意味なので, else if で「でなくて, もし〜ならば」ということになります。 この場合, 「『もしhourが4以上で, かつ, hourが10より小さい場合』でない場合で, かつ, 『もしhourが10以上で, かつ, hourが19より小さい場合』」にその下の行, つまり次が実行されます。

alert("こんにちは。 ");

最後のelseは, 「でなければ」というわけで, 上の2つのいずれにも入らない場合, 次を実行します。

alert("こんばんは。 ");

メモ

ifもelseも, varと同じように予約語で, 特別な目的に使われます。 このため, if, else, varなどの名前を変数として使うことはできません。 たとえば次のような文はエラーになってしまって実行できません。

    if = 3;
    var = else + if;

if文の形式

このようにif ... else if ... else ...を使うといろいろな場合に分けてそれぞれの場合でどのような処理をするかを記述できます。 このような処理を「分岐処理」などと呼びます。 つまり, if文は分岐処理に使われるわけです。

まとめると, if文は次のような形式をもちます。

if (<条件1>) {
  <処理部1>
}
else if  (<条件2>) {
  <処理部2>
}
else if  (<条件3>) {
  <処理部3>
}
...
else {
  <処理部n>
}

else if ...の部分はいくつでも書くことができますし, ひとつもなくてもかまいません。 また, else ...の部分も省略可能です。 if文が使われないプログラムはまずないというほどよく使われますから, これからもいろいろな例が登場します。 else ...が省略されているものなどもそのうち出てきます。

<処理部>には, ひとつ以上の文が並びます。 つまり, if文の中には複数の文がその要素として入ることになります。 「文」の中に「文」が入るわけで, これも「入れ子(nesting)」の一種になります。

メモ

じつは<処理部>に文をひとつだけ書けばよいというときは, 「{」と「}」を省略できます。 しかし, 経験上こうするといろいろな問題を引き起こす誘因になるので, たとえ単純な文がひとつだけの場合でも「{」と「}」で囲むことをおすすめします。 なぜかは, しばらく「棚上げ」しておきます。

条件の条件

<条件>の部分には上で見たように真(true)か偽(false)になる条件を書きます。 たとえば, 「4 <= hour && hour < 10」という式は, hourが4以上10未満の場合にtrue(真)となり, それ以外の場合false(偽)となります。 JavaScriptには, ちょっと奇妙なところがあって, この条件が数字や文字列でもかまいません。 たとえば次のようなif文も構文的には「正しい」文になります。

if (i+j) {
  <実行部>
}

この場合, i+jを実行した結果が0になればifの条件としては偽(false)と判定されます。 それ以外の値になった場合は真(true)として扱われます。 <条件>が文字列でもかまいません。 その場合文字列("")以外は真として扱われます。 慣れないととても奇妙な感じがしますが, そのうち慣れるでしょう。

メモ

プログラムは一般的には上から下に順番に実行されます。 ただし, if文の例でわかるように, いつもすべての部分が実行されるわけではなく, 飛ばされてしまう部分もあります。 また, 次の章で見るように, 同じ部分が何回か繰り返される場合もあります。 ただし, その繰り返される部分についてみれば上から下に順番に実行されることに変わりはありません。

メモ

HTMLの文書でも説明しましたが, プログラムを書くときも字下げ(インデント)をしてわかりやすくすることはとても大切です。

  if (4 <= hour && hour < 10) {  // 午前4時以降10時前まで
    alert("おはようございます。 ");
  }

たとえば, 上の例ではifの条件が満たされた場合に実行されるのが, alert()だけであることが一目瞭然になります。 この後で見る例ではもう少し複雑になります。 字下げの効果をよく確かめてください。 なお, 字下げにもいろいろな流儀があります。 たとえば, 下のように 「{」を次の行に書く人もいます。

  if (4 <= hour && hour < 10)   // 午前4時以降10時前まで
    {
      alert("おはようございます。 ");
    }

大事なことは, 自分の流儀を確立して, それを一貫して使うこと。 少なくとも同じファイルの中では同じ流儀で書くようにしましょう。

さらにif文 ── if文の入れ子

さて, 夏と冬で暗くなる時間はだいぶ違います。 冬には6時頃には真っ暗で, 午後6時30分に「こんにちは」はちょっと変な感じです。 そこで, 上のプログラムを「改良」して, 4月から9月までは上と同じ, これ以外の月については, 1時間早めて午後6時までは「こんにちは」としてみましょう。

プログラム4-2 example04-02.html 季節で分ける

15行目のtoday.getMonth()は, 前にちょっと触れましたが, 月が返ってくる関数です。 注意しなければならないのは, 0から11のどれかが返ってくる点です。 1を足さないと, 日本などで使われている「月」とは合いません。

メモ

コンピュータで扱うときは, 0からはじめるのが「便利」だと言うことになっていて, プログラミング言語の世界では, 多くのものが1からではなく0から始まります。 しかし月を0からはじめるのは, さすがにやりすぎだと思います。 東洋系の人が決めたら, きっと1から12にしたでしょう。 クレジットカードの表記には1から12を使っているのに, なぜ0からにしたのでしょうか?

このプログラムでは, if文の中にさらにif文が入っています。 つまり, if文が入れ子になっているわけです。 外側のif文は次のような構造をしています。

if (4 <= month && month <= 9) {   //4月から9月まで
  <A>
else {   // 1ー3月と10ー12月
  <B>
}

<A>の部分は4月から9月までの間という前提のもとで実行され, <B>の部分はそれ以外のときという前提のもとで実行されます。 <A>, <B>の部分はそれぞれ前に見たのと同じなので説明は省略します。

このように, if文を入れ子にする(ネストする)ことによって, いろいろな場合分けをして処理ができます。 プログラミングの世界ではこの概念は頻繁に登場します。 「入れ子の場合は字下げに気をつける」というのも, だいたい共通です。

メモ

「文の入れ子」は, 日常使う言葉にもある現象です。 「私は, 正君が昨日韓国へ行ったことを知っています。 」という文は, 全体でひとつの文になっていますが, この中に含まれる「正君が昨日韓国へ行った」というのも, 主語と述語をもつ文です。

人間が話す言葉の場合は, 「私は, 克子さんが, 正君が昨日韓国へ行ったことをうらやましがっていることを知っています。 」のように「『文を含む文』を含む文」が現れることはあまりありませんが, プログラミング言語の場合は, このような入れ子の構造が何重にもなります。

if文の中にif文があり, さらにその中に(次の章で出てくる)whileループが, さらにその中にforループがはいるといった構造もまれではありません。 処理をするのは人間ではなく, コンピュータなので, 何重の入れ子になっても問題なく処理してくれるわけです。

じつは, このような何重にも入れ子になった文を処理をするときに, コンピュータも「棚上げ」をします(この棚のことを「スタック(stack)」と呼びます)。

最初の文の処理中に, 入れ子になっている2番目の文の始まりが出てきたら, 最初の文の処理を棚上げして(スタックに積んで), 2番目の処理に移ります。 その処理の途中で3番目の入れ子が始まったら, 2番目の文の処理も棚上げして, 3番目の処理を行う……といった具合です。 n番目の文の処理が終わったら, スタックに積んだn-1番目(ひとつ手前)の処理を再開します。 ……と進んで, 最初の文の処理が終われば, n重の入れ子の文の処理が終わりということになります。

いろいろな「場合分け」

さて, 上のプログラムでは, 最初に「4月から9月まで」と「それ以外の月」と分けて, さらに時刻によって処理を分けましたが, 時刻のほうに最初に注目してもよいのです。 そうした場合, たとえば次のように処理をしても結果は同じになります。

if (4 <= hour && hour < 10) {
  alert("おはようございます。 ");
}
else if (10 <= hour && hour < 18) {
  alert("こんにちは。 ");
}
else if (18 <= hour && hour < 19) {
  if (4<=month && month<=9) { // 4月から9月
    alert("こんにちは。 ");
  }
  else { // 1ー3月, 10ー12月
    alert("こんばんは。 ");
  }
}
else { // 午後7時以降, 翌朝4時より前まで
  alert("こんばんは。 ");
}

夏と冬で分けなければいけないのは, 18時から19時の間だけなので, この部分を分けて処理しています。 ほかのときは夏と冬で分ける必要がありません。 わかりますか?

さらに, 少し複雑になりますが, 次のようにしてもかまいません。

if (4 <= hour && hour < 10) {
  alert("おはようございます。 ");
}
else if ((10 <= hour && hour < 18) ||
        ((18 <= hour && hour< 19) && (4<=month && month<=9) ) )  {
  alert("こんにちは。 ");
}
else {
  alert("こんばんは。 ");
}

この例は「おはようございます。 」「こんにちは。 」「こんばんは。 」を出力するときはいつかを考えて, それぞれの条件を分けたものです。 「||」は「または」を表すものでor(オア)と読みます。 すぐ上の例では「こんにちは。 」を出すところと「こんばんは。 」を出すところが2カ所ずつありますが, この例ではどれも1カ所ずつになっています。

「こんにちは。 」を表示する条件は複雑です。

else if ((10 <= hour && hour < 18) ||
        ((18 <= hour && hour< 19) && (4<=month && month<=9))) 

これは, 「10 <= hour && hour < 18」が成り立つ場合, あるいは 「(18 <= hour && hour< 19) && (4<=month && month<=9)」が成り立つ場合に実行されます。 2つ目の条件はさらに分けると「18 <= hour && hour< 19」であって, かつ 「4<=month && month<=9」である場合に成り立つことになります。 2つ以上の条件が複雑に組み合わさる場合は, 「(」と「)」を使って強い結びつきのほうをまとめるようにしましょう。 結局, 「10時から18時の間であるか, あるいは18時から19時の間であってかつ4月から9月の間である」場合ということを表現していることになります。

ちなみに, この例ではif文の条件が長いために複数の行に分けて書きました。

メモ

この例の場合, 実はまとめるための(...)を使わずに次のように書いても同じように動作します。

    else if (10 <= hour && hour < 18 ||
             18 <= hour && hour< 19 && 4<=month && month<=9)

「&&」, 「||」, 「<」などの「演算子(オペレータ, operator)」には, 結び付きの強さ(優先度)の順番がつけられていて「<=」や「<」は「&&」よりも優先度が強く, 「&&」は「||」よりも優先度が強いのです。 しかし, (...)を使うと優先度に関わらず結び付きの強さを制御できます。 こうしておくと, 優先度の強さに関係なくまとまりを明示できますし, 勘違いを防げるので, とくに複雑な条件の場合は「(...)」を使って, まとめることをお勧めします。

プログラミングが初めての人なら, 一番わかりやすかったのは, おそらく, 夏と冬をまず分けてしまう最初の方法だったと思います。 しかし, 経験を積んでいくと, 一番最後のように「処理ごとに場合分けする」という習慣がついてくるでしょう。

「処理ごとに場合分けする」方が, プログラムは短くなるし, わかりやすくなるのが普通です。 しかし, 例外もあり, 場合分けが複雑になりすぎて理解が困難になることもあります。 いずれにしろ, どういう場合分けをしたのか, 論理的に明確にしておくことが大切です。 理解を助けるために, コメントも加えましょう。

このように, 同じ処理を実現するのに, いろいろな方法(アルゴリズム)が考えられます。 複数のアルゴリズムを思いついた場合, とくに最初のうちは, どうすれば一番わかりやすくなるかを考えて決めるのがよいでしょう。 プログラムを書くときに, まず留意するのは, それが自分にとって, そして他の人にとってわかりやすいかどうかなのです。

メモ

プログラミングと英語

上で見てきたように, プログラミングにはif, elseなどの英単語が使われています。 また, 上の例では変数の名前にも英単語を用いました。 if, elseなどの予約語に英語が使われているのは, コンピュータの世界の「共通語」が英語だからでしょう。 一時期, 予約語にも日本語を使ったプログラミング言語を作ろうという試みがいくつかありましたが, 結局のところ, ほとんど広まらず, 世界で広く使われている言語はすべて英語が予約語として使われています。

変数名や関数名としては, 日本語(漢字やひらがな, カタカナ)が使える言語もありますが, 多くの言語では使えません。 通常は変数や関数の名前は半角の英文字あるいは「_」(アンダースコア)で始まり, 英字または数字, または「_」が続いたものを使います。

JavaScriptでは「$」(ドル記号)も使えますが, 初心者のうちはあえて使う必要はないでしょう(特別な用途に「$」を使う場合があります)。

なお, 最近のJavaScriptでは漢字やひらがな, カタカナなどを変数や関数名として使えるようになっています。 変数名や関数名を英語で考えるのは結構大変ですので, 長い名前を付けるようになったら, 日本語を使ってもよいでしょう。 この時一部の全角の記号(!, ?, $など)は使えない点に注意してください。

最近のコンピュータ(OS)では, ファイル名には, 日本語を使うこともできるのが普通です。 しかし, HTML文書やJavaScriptのプログラムを保存する場合は, ファイル名としてアルファベットや数字, それにハイフン(-)やアンダーバー(_)だけを使っておくのがよいでしょう。 たとえばプロバイダのコンピュータが日本語をきちんと処理してくれずに, 転送したときにおかしな文字に変わってしまう(「文字化け」する)場合があるのです。

ファイル名が文字化けしてしまうと文書が表示できないので, ファイル名に日本語は使わずに, hello5.htmlといったようにしておくのがよいでしょう。 いずれも, いわゆる「半角」の英数字や記号です。 全角の英数字は, 漢字や平仮名と同じように扱われるので, ここで述べたような文字化けの回避には役に立ちません。

ところで「文」を区切るのになぜ「.(ピリオド)」ではなく「;(セミコロン)」を使うのでしょうか。 「.」は3.14など小数点としても使われます。 小数点を表す「.」なのか, 文の終わりを表す「.」なのか, 紛らわしくなるのを避けたかったのです。 プログラムでは「あいまいさ」を扱うのがとても難しいのです。 そのため何でも一意に決まるようにしておくと処理がとても楽になります。

では文の終わりを表す記号として「?」や「!」はどうでしょうか。 確かに文の終わりにはなりますが, 質問ばかり(感嘆ばかり)していてはいつまでたっても仕事が終わりそうにありません(それに「?」や「!」はほかの目的に使われています)。

というわけで, 「.」ほど強くはないが「:」よりも強い区切りとして使われ, ほとんど文の区切りと同じように扱われる「;」が, プログラミングの世界の「文」の区切りとして使われることになったのでしょう。

メモ

予約語, 演算子, 括弧などの間にはいくつでもスペース(半角スペース)を入れることができます(まったく入れなくてもかまいません)。 たとえば, 次のようにまったくスペースを入れずに書いてもかまいません。

    if(10<=hour&&hour<18||18<=hour){
      a=b+c;
      alert("こんにちは。 ");
    }

逆に次のように, スペースをたくさん入れてもエラーにはなりません。

    if   (   10 <= hour    &&   hour < 18){
         a    =   b +     c;
        alert (    "こんにちは。 "   )     ;
     }

同様に次のように, 演算子「.」の前後にスペースを書いても, エラーにはなりません(JavaScriptの処理系がきちんと解釈してくれます)。

    hour = today .  getHours(); 
    month = today  .  getMonth()+1;

ただし, 変数aを宣言して値を代入するといった場合は, 予約語varと変数aの間には必ずひとつ以上の(半角)スペースが必要です。 これを入れないと, 人間同様JavaScriptの処理系も区切りがわかりません。

   vara=3;  // 誤り   var a=3; と varとaの間を離さなくてはいけない

また, 同じ「.」でも, 小数を表す場合は, 前後にスペースがあってはいけません。

   a = 3.  14;  // 誤り   a = 3.14;

どのような表記がエラーになるかは, 厳密に定められていますが, 当面は人間が見て意味が判別できないものはダメだと考えて, コーディング(プログラムの作成)をしてみればよいでしょう。 それで試してみて, JavaScriptの処理系が解釈できなければ, 思い通りの結果が出ないので, 修正することになります。

また, いくらスペースを入れてもよいからといって, 見にくくなるほど入れるのは好ましくありません。 コードを読んだときに理解しやすいようにスペースを入れるようにしましょう。 スペースをどこにいくつ入れるかは, 人によっても違いますが, できるだけ一貫した書き方をしましょう。

よくあるエラー

プログラミング(プログラムの作成)はエラーとの戦いです。 ここまでの例はいずれも比較的短いものでしたが, 何も問題がなくすぐに実行できたという人は, とても優秀な人か, とても運がよかった人でしょう。

プログラムを作成する際には, まず頭の中でどうすれば問題 ── たとえば, 時刻に従って3つのあいさつのいずれかを出す ── を解決できるかをしっかり考える必要があります。 しかし, 考えておいても実際にプログラムを作ってみるとすぐにはうまく動きません。 そのような場合, まず疑ってかかるのは次のような単純なエラーでしょう。

何より問題なのは, こういったエラーをしたときに処理系が人間と同じように考えてくれないことでしょう。 引用符を閉じ忘れときとんでもないところまで引用符の終わりを探しに行って, そのあげくに「オブジェクトが見つかりません」などと訳のわからないメッセージが出たりします(日本語版のブラウザでも, プログラムのエラーメッセージは英語で書かれるのが普通です)。 処理系は, 鍵になる文字列を頼りに「構文解析」を行っていくので, その鍵が見つからないとどこまでも探しに行ってしまうのです。

どのような場合にどのようなエラーや症状になるかは, JavaScriptの処理系によって(つまりブラウザのバージョンや動いているOSによって)だいぶ違うし, これからも変わっていくはずなので一覧にするというわけにもいきません。 いずれにしろ, 何度かエラーを経験して慣れてくると, どのようなエラーをするとどのようなメッセージが出るか見当がつくようになってくるはずです。

難しいのは論理的なエラー

単純な間違い ── 構文的なエラー ── は, 最初は大変でも時間をかければ解決します。 しかし, 一番難しいのは論理的なエラー, プログラムによる問題解決の方法「アルゴリズム」が間違っている場合です。 プログラムが複雑になってくると, 「こうすればうまくいくはずなのにどうしても動かない」といったケースが出てきます。

このような場合は途中の変数の状態などを調べることにより, 自分の考えていた筋書きどおりに動いているかどうかを途中でチェックできます。 上で使ったalert()などの関数を挿入すれば, その時点の変数の値などを調べられます。 また, document.write()を使って, ウェブページに途中結果を書いてしまうという方法もあります。

JavaScriptではconsole.log()という関数がこの目的に一番よく使われます。 この関数を使うと「コンソール」と呼ばれる場所に, 途中経過などを出力することができます。

コンソールを表示するには次の「ショートカット」を利用するのが便利です。

Firefox
Ctrl-Shift-K(WindowsおよびLinux)あるいはCommand-Option-K(Mac)
Chrome
Ctrl-Shift-J(WindowsおよびLinux)あるいはCommand-Option-J(Mac)
Edge
Ctrl-2(F12で「開発ツール」を表示後)
Safari
Command-Option-C(Mac。 ただし, Safariの[環境設定]→[詳細]で[メニューバーに"開発メニュー"を表示]をチェックしておく必要あり)

処理系に付随していることの多い「デバッガ」を使うとこの作業がより簡単になります。 JavaScriptに関しても, いくつかデバッガの役目をしてくれるものが登場しています。 これを使うと, console.log()などで出力しなくても, 途中で実行を止めて変数の状態などを調べられるのです。

いくらプログラミングが上達してもエラー(バグ)から逃れることはできません。 あわてずに落ち着いて対処するのがよいでしょう。 しばらくやってもエラーの原因がわからなかったら, 休養をいれて頭をリフレッシュするのがおすすめです。 できれば, 周りに相談できる人がいると深みにはまらずにすむ場合が多いでしょう。 その人にアルゴリズムを説明するだけで, 自分の頭の中が整理されてバグ(間違い)の原因がわかる場合も多いのです。

まとめ

この章では, 条件によって行う処理を変えるif ... else if ... elseの構文 ── 条件分岐 ── について説明しました。

JavaScriptの構文

JavaScriptで学ぶ 文系の人にもわかるプログラミング入門
第4章 次の章へ