【Javascript】Short-Circuit Evaluation(短絡評価)について(&& and ||)

# 初めに
JavascriptにおけるShort-Circuit Evaluation(短絡評価）について、学習した内容をoutputしてみました。

前回の記事：

https://qiita.com/redrabbit1104/items/e002b51e109e120ed6d4

※内容に間違いなどがある場合はご指摘をよろしくお願いします。

# Short-Circuit Evaluationとは
日本語では短絡評価と呼ばれるShort-Circuit Evaluation。short-circuitという名前通り、ある論理式の評価が決まって値が決定すると残りの部分の論理式を評価せずに終わるという評価方法です。ここでいう論理式とは「&&(and)」や「||(or)」演算子を使った論理式を指します。

# ||(Or)演算子におけるshort-circuit
boolean（trueまたはfalse)ではない値をor演算子を使って比べてみる（評価する）とどうなるでしょうか。
まずはtruthy valuesをor演算子で評価してみました。

```javascript
//truthy values
console.log(1 || 'tanaka');
```
結果は１が表示されます。
![スクリーンショット 2021-05-25 8.03.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e8d63626-aa84-5f19-2ebc-571c60de8176.png)
これは<b>||(or)演算子は||の左辺の値がtruthy valueの場合、右辺を評価せずに素早くtruthy valueである左辺の値を返すから</b>です。1という数字はtruthy valueであるため、1が表示されたわけです。
falsy valueの評価はどうなるでしょう。

```javascript
//falsy values
console.log('' || 1);              //①
console.log(true || undefined);    //②
console.log(undefined || null);    //③
```
結果は以下の通りです。
![スクリーンショット 2021-05-25 8.16.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/c346b57f-b474-efa0-ef1b-4947da35e533.png)
①の場合、''はfalsy valueなので評価されず、truthy valueである1が評価され、画面に1と表示されます。
②の場合、trueはtruthy valueなのでshort-circuitが起こり直ちに評価され、trueと画面に表示されます。undefinedはfalsy valueなので評価されません。
③の場合、undefinedはfalsy valueあので評価されません。また、nullもfalsy valueなので結果的にはshort-circuitが起こらずnullが表示されます。

以下のようにちょっと長いケースを考えてみます。

```javascript
console.log(NaN || '' || undefined || 0n || 'suzuki' || null || 0 || false || 'tanaka');
```
結果はsuzukiと表示されました。
![スクリーンショット 2021-05-25 8.26.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/f2d0730d-3793-ea08-69b1-e6b91af285c2.png)
これは左から順番に処理されていくのですが、NaN, '',  undefined, 0nはfalsy valuesのため評価されず、次の'suzuki'がtruthy valueであるためShort-Circuitが起こりsuzukiが画面に表示されます。'suzuki'に続くnull,0,falseのfalsy valuesやtruthy valueの'tanaka'は評価されず処理が終わります。

このように<b>||演算子のshort-circuitは左から順にtruthy value(真）を探しに行き、見つかったらその値を評価し処理を終わらせます。</b>
また、<b>truthy valuesが見つからなかった場合、一番最後の値を結果として返します。</b>

### ||(or)演算子のshort-circuit応用例
簡単なobjectを例にして||演算子のshort-circuitを試してみました。
例えばobjectの値が存在するかどうか分からない場合、or演算子のshort-circuitを利用して、デフォルト値を指定できます。

```javascript
const trees = {
      numTrees: 53
}

const yearOfTrees = trees.Year || 20;
console.log(yearOfTrees);
```
trees.yearは存在しないためundefinedでありfalsy valueです。そのため、trees.Yearは評価されず、truthy valueである20が評価され画面に表示されます。
![スクリーンショット 2021-05-25 8.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/45c2e73c-bf4d-d945-cc69-df4ae2f68a3c.png)

# &&(And)演算子におけるshort-circuit
&&(And)演算子の場合はどうなるでしょう。結論から言いますと&&(And)演算子のshort-circuitは||(Or)演算子の真逆の動きをします。

```javascript
//And演算子
console.log(0 && 'tanaka');
```

0がfalsy valueであるため、short-circuitが起こり評価され処理が終わります。
![スクリーンショット 2021-05-25 9.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/dedb487e-83a9-5953-82fb-76d30f4c6890.png)

両方ともtruthy valuesの場合はどうなるでしょう。

```javascript
//8も'tanaka'もtruthy values
console.log(8 && 'tanaka');
```
8は数字でありtruthy valueなので評価されません。また、'tanaka'もtruthy valueなのでshort circuitは起こらず結果として'tanaka'を返します。
![スクリーンショット 2021-05-25 9.07.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/d51d907e-8f0f-ecb6-9acb-2d3705eba020.png)
||(or)演算子と同じように長い例で考えてみます。

```javascript
console.log(1 && 'hello' && 3 && true && 'undefined' && 1 && undefined && 0 && false && 'tanaka');
```
1,'hello',3,true,'undefined',1は全てtruthy valuesなので評価されず、その次のundefinedはfalsy valueのためshort-circuitが起こり評価され処理が終わります。
![スクリーンショット 2021-05-25 9.12.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/ac048b28-118c-7bcf-6896-5dee512ae15c.png)
このように<b>&&演算子のshort-circuitは左から順にfalsy value(偽）を探しに行き、見つかったらその値を評価し処理を終わらせます。</b>
また、<b>falsy valuesが見つからなかった場合、一番最後の値を結果として返します。</b>

### &&(and)演算子のshort-circuit応用例
objectにprintTreesという関数が定義されているとします。printTreesとprintPeopleという関数がそれぞれ定義されているのかどうか知らない場合、&&演算子のshort-circuitを使えば関数が存在しない場合にエラーが表示されないようにすることができます。

```javascript
const trees = {
  printTrees: function () { console.log('松', '竹', 'ヒノキ') }
}

//関数printTreesが存在する場合
trees.printTrees && trees.printTrees();
//関数printPeople()が存在しない場合
trees.printPeople && trees.printPeople();
```
画面にはprintTrees();関数の結果だけが表示されます。
![スクリーンショット 2021-05-25 9.33.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e0fe4b5f-06de-7ab5-c1aa-9ffdc376614a.png)

関数printTreesは存在するのでtruthy valueであり、trees.printTreesは評価されず最後のtrees.printTrees();が実行されます。
一方、trees.printPeopleは存在しないためfalsy valueとして評価されshort circuitが起こり評価され処理が終わります。

# 参考サイト
https://codeburst.io/javascript-what-is-short-circuit-evaluation-ff22b2f5608c
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
https://qiita.com/dinasetiana/items/2b0cb63e91e9511d1c6e