👻

[初学者向け]JavaScriptにおける論理演算子の罠:||と比較演算子の使い方

2023/07/02に公開

こんにちは。今回はNextjsで条件分岐を書いている際に出会ったちょっとした論理演算子のミスを共有したいと思い記事を書きました。
JavaScriptを扱う際、論理演算子 ||(OR)と等価演算子(===)を一緒に使用するときには注意が必要です。なぜなら、これらをうまく組み合わせないと思わぬ振る舞いを引き起こす可能性があるからです。

それでは考えてみましょう。以下の式を見てください。

const foods = ["apple", "orange", "fish", "meat"];

foods.map((food) => {
    if (food === "apple" || "orange") {
        console.log("Fluet!");
    } else {
	console.log("Not Fluet!");
    }
});

このコードを見たとき、何を期待しますか? 配列foodsの中からfoodが"apple" または "orange" の場合、"Fruit!" がコンソールに出力されると思うかもしれません。しかし実際には、このコードは何があっても "Fruit!" を出力します。これは、JavaScriptでは "orange"(空でない文字列)が true と評価されるためです。

上記の表現は次のように評価されます:

まず、food === "apple" を評価します。もし food が "apple" なら、全体の結果は true になります。
しかし、もし food が "apple" でない場合(つまり food === "apple" が false である場合)、次に "orange" を評価します。非空の文字列 "orange" 自身は true と評価されるため、全体の結果は true となります。
なのでこの条件式は「(food が "apple"かどうか)または,true」という条件式になってしまっているのですね。つまり、この式全体はfoodの値に関係なくtrueになってしまいます。

この問題を解決するには、両方の条件を明示的に指定する必要があります:

const foods = ["apple", "orange", "fish", "meat"];

foods.map((food) => {
    if (food === "apple" || food === "orange") { 
        console.log("Fluet!");
    } else {
	console.log("Not Fluet!");
    }
});

こうすれば、foodが "apple" または "orange" の場合に限り、"Fruit!" が出力されるようになります。

Discussion