JavaScript 論理演算子 AND OR

本記事では論理演算子のAND、OR演算子を紹介します。

論理演算子

論理演算子は基本的に真偽値を扱う演算子です。

AND演算子は両辺の演算子がどちらも、trueであればtrueを返し、そうでなければfalseを返す、OR演算子は両辺の演算子がどちらも、falseであればfalseを返し、そうでなければtrueを返すという演算子です。

AND演算子(&&)

AND演算子(&&)は、左辺の値の評価結果がtrueに変換できるならば、
右辺の評価結果を返します。
一方で、左辺の値の評価結果がfalseに変換できるならば、
右辺は評価されること無く、左辺の値がそのまま返されます。

このような値が決まった時点でそれ以上評価しないような評価のことを
短絡評価(Short-circuit evaluation)と呼びます。

// 左辺はtrueであるため、右辺の評価結果を返す
console.log(true && true); //true
console.log(true && false); //false
// 左辺がfalseであるなら、その時点でfalseを返す。 右辺は評価されない
console.log(false && true); //false
console.log(false && false); //false

また、AND演算子は左辺を評価する際に、左辺を真偽値へと暗黙的な型変換をしてから判定します。 真偽値への暗黙的な型変換ではどの値がtrueでどの値がfalseになるかは、次のルールによって決まります。

falsyな値はfalseになる

falsyでない値はtrueになる

falsyな値とは以下の値のことを言います。

  • false
  • undefined
  • null
  • 0
  • -0
  • 0n
  • NaN
  • ""や''や``(空文字列)

trueへと変換される値の種類は多いため、falseへと変換されない値はtrueとなると考えておけば十分だと思います。 このオペランドを真偽値に変換してから評価するのはAND、OR演算子で共通の動作です。

次のように、AND演算子(&&)は左辺を真偽値へと変換した結果がtrueの場合は、右辺をそのまま返します。 左辺がfalsyの場合は、右辺は評価されず、左辺がそのまま返されます。

// 左辺はfalsyではないため、評価結果として右辺を返す
console.log(true && 'hello'); //hello
console.log('other' && 'hello'); //hello
// 左辺がfalsyであるため、評価結果として左辺を返す
console.log(false && 'hello'); //false
console.log(undefined && 'hello'); //undefined
console.log(null && 'hello'); //false
console.log(0 && 'hello'); //0
console.log(-0 && 'hello'); //-0
console.log(0n && 'hello'); //On
console.log(NaN && 'hello'); //NaN
console.log("" && 'hello'); //空文字列

AND演算子の利用例

論理演算子は、if文と組み合わせて利用することが多い演算子です。

例1

次のように、numberが3で割り切れかつ 5で割り切れる場合という条件をひとつの式として書くことができます。

let number = 15;
if (number % 3 == 0 && number % 5 == 0) {
    console.log(number);
}

// if文のネストで書くと以下のようになる let number = 15; if (number % 3 == 0) {     if (number % 5 == 0) {         console.log(number);     } }
//出力 15

AND演算子(&&)を使うと、if文のネストに比べて短く書くことができます。

なお、このときに、numberが3で割り切れない(例えば5等の)場合は、その時点でif文の条件式はfalseとなります。 そのため、AND演算子(&&)の右辺は評価されずに、if文の中身も実行されません。

例2

let password = "123456";
if (password  && password.length < 8) {
    console.log('パスワードは8文字以上で入力してください。');
}

この例では、passwordのlengthプロパティを確認し、8よりも小さければエラーメッセージを設定しています。

変数passwordに格納された文字列の長さを見ています。

なので、やりたいことだけを書くと、以下のようなプログラムになりそうです。

if (password  && password.length < 8) {
    console.log('パスワードは8文字以上で入力してください。');
}

ただし、この書き方はよくないです。

これはJavaScript以外の言語にもいえますが、
オブジェクトのpropertiesを参照する時には、そのオブジェクト自体が
nullやundefinedである可能性を考慮しなければいけません。
(厳密な言い方をすると、nullやundefinedはプリミティブだから、
propertiesを持てないのですが、本記事では詳細を割愛します。)

つまり、以下のような書き方をした時に、
エラーが発生し、プログラムが終了してしまいます。

let password;
if (password  && password.length < 8) {
    console.log('パスワードは8文字以上で入力してください。');
}

// 出力 // Error evaluating Javascript output:  TypeError: Cannot read properties of undefined (reading 'length')

上記の例ではpasswordは宣言されただけで、何も値が代入されていません。

そのため変数passwordの中身はundefinedになっているのですが、

if分の中ではpassword.lengthという形で、passwordのpropertiesを呼び出しています。

当然undefinedにはlengthという名前のpropertiesはありません。

そのため、エラーが生じてしまうのです。

それを防ぐために、

password &&

という記載を追加します。

つまり、passwordに値が代入されていない場合は、
エラーが発生するプログラムが実行される前に、処理を打ち切ります。

passwordの中身がnullやundefinedだった場合には、
AND演算子の左側の値がfalseであるとみなされ、その時点で処理が打ち切られるので、
エラーが発生するpassword.lengthという処理が実行されません。

この書き方はよく用いられます。

OR演算子(||)

OR演算子(||)は、左辺の値の評価結果がtrueに変換できるならば、そのまま左辺の値を返します。 一方で、左辺の値の評価結果がfalseならば、右辺の評価結果を返します。

// 左辺がtrueなので、左辺の値が返される
console.log(true || true); //true
console.log(true || false); //true
// 左辺がfalseなので、右辺の値が返される
console.log(false || true); //true
console.log(false || false); //false

また、AND演算子と同様に、OR演算子は左辺を評価する際に、左辺を真偽値へと暗黙的な型変換します。 次のように、OR演算子は左辺がfalsyの場合には右辺の値を返します。

// 左辺はfalsyではないため、左辺の値が返される
console.log(true || 'hello'); //other
console.log('other' || 'hello'); //other
// 左辺がfalsyなので、右辺の値が返される
console.log(false || 'hello'); //hello
console.log(undefined || 'hello'); //hello
console.log(null || 'hello'); //hello
console.log(0 || 'hello'); //hello
console.log(-0 || 'hello'); //hello
console.log(0n || 'hello'); //hello
console.log(NaN || 'hello'); //hello
console.log("" || 'hello'); //hello

OR演算子の利用例

例1

今までは1つの式に1つの演算子を使った例だけを紹介しましたが、多数の演算子を用いることができます。
let firstName = "";
let lastName = "mue"; let userName = "駆け出しエンジニア"; const name = firstName || lastName || userName || "Anonymous";
console.log(name); 
// 出力 mue

上記の例では、firstName、lastName、userNameの順に値を確認していき、trueに変換できるものがあれば、それ以降は評価されず、その値が出力されます。変換できるものが無ければ、Anonymousが出力されるようになっています。

例2

let obj = { test: 'test' };
obj = obj || {};
console.log(obj); 
 //出力 { test: 'test' } 
let obj ;
obj = obj || {};
console.log(obj); 
 //出力 {}

上記2つのコードの2行目をみてください。obj が未定義ならば、obj を生成され、すでに存在してる場合は、そのまま使うということをやっています。

なぜこんな紛らわしい書き方をするかというと、AND演算子の使用例でも述べたように、
オブジェクト自体がnullやundefinedである可能性を考慮しなければいけないからです。

変数に自分自身を代入する読みにくい変なコードなのですが、
初期値を指定する際などに、非常によく使われる書き方なので覚えておきましょう。

参考文献

・ITやWebに関する備忘録 IT / Web技術. JavaScriptのANDとOR【現場でよく使われる特殊な書き方】. <https://web.lingual-ninja.com/2019/07/javascript-and-or.html> (参照日2022年10月8日).
・JavaScript Primer. 演算子. <https://jsprimer.net/basic/operator/> (参照日2022年10月8日).
・ゼロプラスワン. JavaScript 論理演算子OR「||」の特殊な用法. <https://zero-plus-one.jp/javascript/javascript-logical-operators-or/> (参照日2022年10月8日).

0 件のコメント:

コメントを投稿

人気の投稿