処理を分岐させる

if文

JavaScriptではスクリプトを実行すると上から順番にステートメントを1つずつ処理していきます。
しかし、コーディングを進めていくと処理を分岐させたい場面があります。
このような分岐処理を実現する命令の一つが if文 です。
if文は「もし〇〇ならば〇〇する」という処理を実現することができます。構文は下記の通りです。

if (条件式) {
  // 条件式がtrueの場合に実行する処理
}

if文では丸括弧の中に条件式を記述します。
条件式は判定の結果がtrueまたはfalseになる式です。
条件式の結果がtrueであれば中括弧の中の処理が実行され、falseであれば中括弧の中の処理は実行されません。
(この中括弧の中を ブロック といいます。)
下記のサンプルを記述して実行してみましょう。

function outputBranch_1() {
  var x = 10;
  if (x > 1) {
    console.log('xは1よりも大きいです。');
  }
}

xは1よりも大きいです。

if else 文とelse if文

if文の条件式の結果がfalseだった場合に別の処理をさせたい場合は if else 文 を使用します。

if (条件式) {
  // 条件式がtrueの場合に実行する処理
} else {
  // 条件式がfalseの場合に実行する処理
}

条件式がtrueの場合はifブロック内の処理が実行され、falseの場合はelseブロック内の処理が実行されます。
下記はif else 文のサンプルになります。変数xに代入する値を変更しながら複数回実行して、意図したブロックの処理が実行されるか確認してみましょう。

function outputBranch_2() {
  var x = 10;
  if (x > 10) {
    console.log('xは10よりも大きいです。');
  } else {
    console.log('xは10以下です。');
  }
}

xは10以下です。

if else 文では、条件式がtrueかfalseかで処理を分岐することができます。
また、分岐を3つ以上にしたい場合は if else if文 を使うと必要な分だけ条件分岐の処理を作ることができます。

if (条件式1) {
  // 条件式1がtrueの場合に実行する処理
} else if (条件式2) {
   // 条件式2がtrueの場合に実行する処理
   ・・・
} else {
  // すべての条件式がfalseの場合に実行する処理
}

条件式1、条件式2と順番に条件式を判定していき、最初に条件式がtrueだった際に該当のブロック内の処理をします。
また、最後のelseは省略することができます。
下記のサンプルを実行して、if else 文の動作を確認してみましょう。

function outputBranch_4() {
  var x = 10;
  if (x < 10) {
    console.log('xは10よりも大きいです。');
  } else if (x < 20) {
    console.log('xは10以上で20よりも小さいです。');
  } else {
    console.log('xは20以上です。');
  }
}

xは10以上で20よりも小さいです。

else if文でいくつでも条件分岐の処理を追加することができますが、あまりに多いと読みづらいコードになってしまいます。
この後登場する論理演算子やswitch文を活用したりして、else if文を多用することは避けるようにしましょう。


比較演算子とは

これまで登場した「<」は数学と同じく、左辺と右辺を比較して左辺の方が小さければ条件式としてtrueを返します。
このような条件式内で使用し、左辺と右辺を比較してtrue、またはfalseを返す役割を持つ演算子を 比較演算子 といいます。
JavaScriptで使用できる比較演算子は下記の通りです。

比較演算子 概要 使用例
== 左辺と右辺の値が等しい場合はtrue 10 == ‘10’
!= 左辺と右辺の値が等しくない場合はtrue 10 != 11
< 左辺が右辺より小さい場合はtrue 10 < 11
<= 左辺が右辺以下の場合はtrue 10 <= 11
> 左辺が右辺より大きい場合はtrue 10 > 9
>= 左辺が右辺以上の場合はtrue 10 >= 9
=== 左辺と右辺が値もデータ型も等しい場合はtrue 10 === 10
!== 左辺と右辺が値もデータ型も等しくない場合はtrue 10 !== ‘10’

この比較演算子には注意すべき点があります。
下記のサンプルを実行するとログにはtrueとfalseのどちらが出力されるでしょうか?

function outputComparison_1() {
  var fruits_1 = ['apple', 'grape'];
  var fruits_2 = ['apple', 'grape'];
  console.log(fruits_1 == fruits_2); // false

  var person_1 = {name: 'Taro'};
  var person_2 = {name: 'Taro'};
  console.log(person_1 == person_2); // false
}

出力されたログの結果は共にfalseになります。
実は、配列やオブジェクトを変数に代入した場合に、実際に変数に格納されるのはメモリ上のアドレス(参照値)です。
したがって、要素や構造が全く同じであったとしても、物理的に別のアドレスに割り当てられている配列またはオブジェクト同士の比較はfalseとなります。
一方で、下記のサンプルを実行するといずれのログもtrueとなります。
それぞれの変数に格納されているアドレスは等しいため比較結果はtrueとなります。

function outputComparison_2() {
  var fruits_1 = ['apple', 'grape'];
  var fruits_2 = fruits_1;
  console.log(fruits_1 == fruits_2); // true

  var person_1 = {name: 'Taro'};
  var person_2 = person_1;
  console.log(person_1 == person_2); // true
}

配列とオブジェクトの比較はその参照値の比較となります。

寛容な比較と厳密な比較

「==」と「===」の違いと、「!=」と「!==」の違いについて確認していきましょう。

等価演算子には通常の等価演算子(==)と厳密等価演算子(===)があります。
「==」と「!=」はデータ型は考慮せずに値を比較しているのに対し、
「===」と「!==」は比較の際にデータ型も考慮します。

厳密等価演算子(===)で2つの値が「厳密等価」であると見なされるのは次のいずれかです。

  • 同じオブジェクトを参照しているとき
  • プリミティブ型で、データ型も値も同じであるとき

一方、等価演算子(==)は厳密等価より緩い条件で評価します。

  • 同じオブジェクトを参照しているとき
  • 「同じ値に変換される」とき

下記のサンプルでそれぞれの演算子の違いを確認していきましょう。

function outputComparison_3() {
  // 「==」と「===」の違い
  console.log(10 == '10'); // true
  console.log(10 === '10'); // false
  // 「!=」と「!==」の違い
  console.log(10 != '10');  // false
  console.log(10 !== '10'); // true
}

「==」と「!=」は寛容な比較(データがを考慮しない)を行いますが、データ型を考慮しなかったために想定外の結果を引き起こす可能性があります。
そのため、「===」と「!==」を使用する方がより安全に開発することができます。

論理演算子とは

if文の複数の条件式を同時に判定させたいケースがありますが、現時点では下記のように記述することができます。

function outputLogical_1() {
  var x = 11;
  if (10 < x) {
    if (x <= 20) {
      console.log('xは10よりも大きく、20以下です。');
    }
  }
}

xは10よりも大きく、20以下です。

このようにif文をネスト(入れ子)にすることで複数条件で判定することができますが、
条件が増えるごとにネスト(入れ子)が増えていきどんどん複雑になっていきます。
実は複数条件をシンプルに記述できる演算子があり、これを 論理演算子 といいます。
JavaScriptで使用できる論理演算子は下記の通りです。

論理演算子 概要 使用例
&& 左辺と右辺がいずれもtrueであればtrue x === 10 && y === 100
|| 左辺と右辺がいずかがtrueであればtrue x === 10
! 条件式の結果を反転させる !(x === 10)

この論理演算子を使用すると、先ほどのサンプルを下記のように記述することができます。
他の論理演算子の結果と合わせて確認しましょう。

function outputLogical_2() {
  var x = 11;
  if (10 < x && x<= 20) {
    console.log('xは10よりも大きく、20以下です。');
  }
  if (10 < x || x<= 20) {
    console.log('xは10よりも大きい、または20以下です。');
  }
  if (!(x < 10)) {
    console.log('xは10より小さくないです。');
  }
}

xは10よりも大きく、20以下です。
xは10よりも大きい、または20以下です。
xは10より小さくないです。

switch文

if文による条件分岐では、条件式がtrueかfalseかのどちらかしか分岐処理を記述することができません。
それ以上の分岐処理を行いたい場合は先ほど紹介したelse if文で追加することもできますが、
あまりにも追加する条件式が多い場合は switch文 を使用するとよいでしょう。
switch文は、ある式が複数の値のいずれかと一致するかの判定を行うことができ、下記のような記述で実現することができます。

switch () {
  case 値1:
    // 式 === 値1であるときの処理
    break;
  case 値2:
    // 式 === 値2であるときの処理
    break;
  default:
    // 式がいずれの値にも一致しなかったときの処理
}

switch文では、式の結果と一致する値を、値1、値2・・・の中から探します。
一致する値が存在すれば、その case節 のステートメントの処理を順次実行していきます。
break文 でswitch文から抜け出し、式の結果と一致する値が存在しなければ default節 のステートメントの処理を実行します。

例として、下記のサンプルを実行してみましょう。
fruit変数に代入されている値によって出力されるログの内容が変わりますので、fruit変数に代入する値を変えてみて複数回実行して確認してみましょう。

function outputBranch_5() {
  var fruit = 'apple';
  switch(fruit) {
    case 'apple':
      console.log('りんご');
      break;
    case 'grape':
      console.log('グレープ');
      break;
    case 'orange':
      console.log('オレンジ');
      break;
    default:
      console.log('知らないフルーツです!');
  }
}

りんご

break文

各case節の処理の末尾にあるbreak文は省略することができますが、原則各case節ごとにbreak文を記述することになります。
どうしてbreak文が必要なの?と思われるでしょうが、それは下記のサンプルを実行するとわかります。

function outputBranch_6() {
  var fruit = 'apple';
  switch(fruit) {
    case 'apple':
      console.log('りんご');
    case 'grape':
      console.log('グレープ');
    case 'orange':
      console.log('オレンジ');
    default:
      console.log('知らないフルーツです!');
  }
}

りんご
グレープ
オレンジ
知らないフルーツです!

実行してみると値が一致している「‘apple’」のcase節だけではなく、その他のcase節のログも出力されてしまいます。
実は、switch文は式に該当するcase節の処理以降の全ての処理を実行する という仕様になっているのです。
あえて、値が一致したcase節の以降を全て実行させたい場合はbreak文を書く必要はないのですが、各case節ごとでswitch文を抜けたい場合はbreak文を使用します。

switch文はbreak文がない限りブロックから抜け出すことはありません。