論理演算子「論理積(&&)」と「論理和(||)」「論理否定(!)」について調べました【JavaScript】

JavaScript

JavaScriptの論理演算子について、分かっているようで分からなかったのでメモ。

論理演算子とは

そもそも論理演算子とはなんぞや?ですが、主にif文で使います。
下記のように「&&」「||」「!」を使って条件を判定します。

// True判定されると、コンソールが表示されます

if(1 || null)  { // aまたはbがTrueの場合はTrue判定される
  console.log("条件に合致しました");  //出力される
}

if(1 && null) { // aとbがTrueの場合はTrue判定される
  console.log("条件に合致しました");  //出力されない
}

if(!(1 && null)) { // Trueの場合False、Falseの場合はTrue判定される
  console.log("条件に合致しました");  //出力される
}

条件式のif文で、どれか1つでも条件に一致していれば実行、全て一致していなければ実行しない。といった使い方をします。

記号の意味は次の通りです。

論理積&&判定全てがTrueの場合、Trueを返す
論理和||判定の1つでもTrueの場合、Trueを返す
論理否定!実際の判定の逆を返す。
判定がTrueの場合は、False を返し、Falseの場合は、True を返す。

True、Falseになる値にはどんなものがあるか

先ほどの条件式では、数字の1がTrue判定されています。
何もないことを表すnullなら何となく分かりますが、数字の1がどうしてTrue判定されるのか、、?
調べたところ、Falseになるのは主に次の値です。これ以外はTrueになると思います。

Falseになる値

  • 0(数字)
  • NaN
  • 空文字
  • null
  • undefind

実際の判定結果をconsole.logに出力しました。判定結果をTrue、Falseで表示させるために(!!)で判定結果を逆の逆にしています。なお、数字の0を厳密に判定するには、Number()メソッドで数値に変換してあげた方が良いらしいです。

console.log("0の判定結果:" + !!(Number(0)));
console.log("NaNの判定結果:" + !!(NaN));
console.log("空文字の判定結果:" + !!(""));
console.log("nullの判定結果:" + !!(null));
console.log("undefinedの判定結果:" + !!(undefined));

See the Pen resultConditionFalse by donguri2020 (@m-ke) on CodePen.

Trueになる値

Falseになる値以外がTrueになりますが、勘違いしそうなものをまとめました。

  • 数字の0以上
  • 空の配列
  • 空のオブジェクト
  • 空でない文字列

こちらの判定結果を確認してみます。

console.log("1の判定結果:" + !!(1));
console.log("空配列の判定結果:" + !!([]));
console.log("空のオブジェクトの判定結果:" + !!({}));
console.log("空でない文字列の判定結果:" + !!("あいうえお"));

実際の判定結果は次のようになります。

See the Pen resultConditionTrue by donguri2020 (@m-ke) on CodePen.

論理積(&&)の挙動について

論理積(&&)は、左の値がFalseになったらその時点で値を返し、それ以降の判定は無視されます。
例えば、次の条件式の場合はFalseが返ってきます

10 < 20の判定は無視される

上記は条件式の判定を比較演算の結果にしています。この場合、結果はFalseになります。
この条件式を変数に格納すると、結果的にはfalseが格納され、if文で条件判定すると、結果はFlaseになることが確認できます。

const conditions = 10 < 0 && 10 < 20; //変数にfalseが格納される
if(conditions) {
    return "Trueでした"; // 無視される
  } else if(!conditions) {
    return "Falseでした"; // 返却される
  }

次は、先ほどのように比較演算でなく、値を条件式に指定した場合です。
左の値がTrueだと、右の値が返却されます。False判定された値がそのまま返却されます。

falseである空の文字が返却される

この場合、変数「conditions」には空文字が格納され、if文の判定はFalseになります。

const conditions = "テスト" && ""; //変数に空文字が格納される
if(conditions) {
    return "Trueでした"; // 無視される
  } else if(!conditions) {
    return "Falseでした"; // 返却される
  }

条件式の数が増えても同様で、左から順番に判定して、Falseになった時点でその値を返却し、それ以降の判定は無視されます。

null以降の条件式は無視される
const conditions = 10 && null && 20; //変数にnullが格納される
if(conditions) {
    return "Trueでした"; // 無視される
  } else if(!conditions) {
    return "Falseでした"; // 返却される
  }

判定が全てTrueになった場合、一番右側の値が返却されます。

この場合、一番右側の20が返却されるので条件判定はTrueになります。

const conditions = 10 && 15 && 20; //変数に20が格納される
if(conditions) {
    return "Trueでした";  // 返却される
  } else if(!conditions) {
    return "Falseでした"; // 無視される
  }

実際の判定結果はこちらで確認できます!

See the Pen && by donguri2020 (@m-ke) on CodePen.

論理和(||)の挙動について

論理和(||)は論理積と逆で、左の値がTrueになったらその時点で値を返し、それ以降の判定は無視されます。
例えば、次の条件式の場合はTrueが返ってきます。

10 < 0の判定は無視される

上記の条件式も判定を比較演算の結果にしています。この場合、結果はTrueになります。
この条件式を変数に格納すると、結果的にはtrueが格納され、if文で条件判定すると、結果はTrueになることが確認できます。

const conditions = 10 < 20 || 10 < 0; //変数にtrueが格納される
if(conditions) {
    return "Trueでした"; // 返却される
  } else if(!conditions) {
    return "Falseでした"; // 無視される
  }

次は、先ほどのように比較演算でなく、値を条件式に指定した場合です。
左の値がFalseだと、右の値が返却されます。True判定された値がそのまま返却されます。

Trueである”てすと”の文字列が返却される

この場合、変数「conditions」には「てすと」の文字列が格納され、if文の判定はTrueになります。

const conditions = "" || "てすと"; //変数に「てすと」の文字列が格納される
if(conditions) {
    return "Trueでした"; // 返却される
  } else if(!conditions) {
    return "Falseでした"; // 無視される
  }

条件式の数が増えても同様で、左から順番に判定して、Trueになった時点でその値を返却し、それ以降の判定は無視されます。

10以降の条件式は無視される
const conditions = null || 10 || 0; //変数に10が格納される
if(conditions) {
    return "Trueでした";  // 返却される
  } else if(!conditions) {
    return "Falseでした"; // 無視される
  }

判定が全てFalseになった場合、一番右側の値が返却されます。

この場合、返却される値が0なので、条件判定はFalse になります。

const conditions = null || 0 || 0; //変数に0が格納される
if(conditions) {
    return "Trueでした";  // 無視される
  } else if(!conditions) {
    return "Falseでした"; // 返却される
  }

実際の判定結果はこちらで確認できます!

See the Pen JavaScriptOR by donguri2020 (@m-ke) on CodePen.

論理和(||)で初期値を設定する

論理和(||)で時々見かける使い方についてメモしておきます。
例えば、以下のように挨拶を返す関数があるとして、引数greetingの値がない場合、初期値を決めておきたい!とします。

ポイントは色付けしている変数greetingTextに代入している論理和(||)です。

// 挨拶を返す関数
function fc(name, greeting) {
  // 引数greetingに値がなければ「こんにちは」が変数に格納される
  const greetingText = greeting || "こんにちは";
  return `${greetingText}。${name}さん`;
}
console.log(fc("マイク", "ハロー")); // ハロー。マイクさん
console.log(fc("花子")); // こんにちは。花子さん

論理和(||)を使えば、引数greetingに値があれば引数の値が変数に格納され、値がない場合はFalse判定となるので、右側の値「こんにちは」が変数に格納されることになります。

if文で判定することもできますが、論理和(||)を使うことでスッキリ記述することができます!

注意点は、False判定される0を引数にすると挙動が想定した通りにならないことです。

論理否定(!)の挙動について

論理否定(!)は実際の判定の逆を返します。
判定がTrueの場合はFalse を返し、Falseの場合はTrue を返します。

判定の逆を返すので、スイッチのような動きを実装したい時によく使います。
簡単なサンプルを作りました。

See the Pen CountUp by donguri2020 (@m-ke) on CodePen.

ボタンをクリックするとカウントアップし、3か15の倍数の時にスイッチがオンになります。
スイッチのオンオフの部分だけ抜き出したコードがこちらです。

const countUpBtn = document.getElementById("countUpBtn");
const icon = document.getElementById("icon");
let flag = false; // オンオフ判定のフラグ

// スイッチオンオプ
const showIcon = (flag) => {
  if(flag) {
    icon.innerHTML = '<i class="fas fa-toggle-on"></i>';
  } else {
    icon.innerHTML = '<i class="fas fa-toggle-off"></i>';
  }
}

// ボタンクリック
countUpBtn.addEventListener('click', () => {
  showIcon(flag);
  if(addNum % 15 == 0) {
      showIcon(!flag);
   } else if(addNum % 3 == 0) {
      showIcon(!flag);
   } else if(addNum % 5 == 0) {
      showIcon(!flag);
    }
});

さらに細かくみていきます。まずオンオフを判定する変数を設定します。
初期値はFalseです。

// オンオフ判定のフラグ
let flag = false; 

スイッチのオンオフの切り替えをする関数showIconを作成します。
引数flagの値がTrueならオンにしてFalseならオフにします。

// スイッチオンオプ
const showIcon = (flag) => {
  if(flag) {
    icon.innerHTML = '<i class="fas fa-toggle-on"></i>';
  } else {
    icon.innerHTML = '<i class="fas fa-toggle-off"></i>';
  }
}

カウントアップのボタンをクリックした時、スイッチのオンオフの切り替えをする関数showIconを実行しますが、引数のflagを論理否定(!)で渡すと、現状のflagの逆の状態を渡すことになります。結果的にオンオフが実装できます。

// ボタンクリック
countUpBtn.addEventListener('click', () => {
  showIcon(flag); // 該当しない数字の場合False
  if(addNum % 15 == 0) {
      showIcon(!flag); // Falseの反対Trueを引数で渡す
   } else if(addNum % 3 == 0) {
       showIcon(!flag); // Falseの反対Trueを引数で渡す
   } else if(addNum % 5 == 0) {
       showIcon(!flag); // Falseの反対Trueを引数で渡す
    }
});

まとめ

なんとなく使っていた論理演算子を改めてまとめました。
基礎中の基礎とはいえ、意外と分かっていない部分もあったのでスッキリしました。

特に変数の代入ではコードがスッキリかけます。今後も積極的に使っていきたいと思います!

コメント