演算子の優先順位
このレッスンで分かること
- 演算子には強さの順序があり、
&&は||より先に評価されます- 迷ったら丸括弧を書きます。実行結果は同じでも、読む速度が変わります
同じ 1 行が 2 通りに読めてしまう
算数の 2 + 3 * 4 が 20 ではなく 14 になるのと同じで、JavaScript の式も演算子ごとに強さが決まっています。強いものから順にまとまりを作りながら評価されます。
JavaScript
console.log(2 + 3 * 4); // 14 掛け算が先
console.log((2 + 3) * 4); // 20 括弧が最優先比較や論理演算子が並ぶと、算数の直感が効かなくなります。プロフィールサイトの表示条件で見てみます。
JavaScript
const hasPhoto = true;
const likes = 40;
const isPinned = true;
console.log(hasPhoto && likes >= 100 || isPinned); // trueこの式は「写真があって、かついいねが 100 以上、または、ピン留めされているなら真」と読めます。ただしそう読めるのは、&& が || より強いと知っている人だけです。知らない人は「写真があって、かつ、いいねが 100 以上またはピン留め」と読むかもしれません。同じ文字列から 2 通りの意味が読み取れてしまう、というのが問題です。
覚えるのは 3 行だけ
優先順位の一覧は長いのですが、日常で効いてくるのは次の 3 つです。
- 算術は比較より強い。
likes + 10 >= 100は(likes + 10) >= 100と解釈される - 比較は論理より強い。
likes >= 100 && hasPhotoに括弧は要らない &&は||より強い。a && b || cは(a && b) || cと解釈される
JavaScript
console.log(false && false || true); // true (false && false) || true
console.log(false && (false || true)); // false 括弧で結果が変わった同じ並びでも、括弧の位置で結果が変わります。&& が先だと知らなければ、この違いに気づけません。
順序は「算術 → 比較 → 論理」で、論理の中では
&&が||より先です。算数で掛け算を先に計算するのと同じ並びだと思うと覚えやすいですが、返る値まで算数と同じではありません。1 || 1は2ではなく1です。
括弧は読む人のために書く
優先順位を暗記していれば括弧は省けます。しかし省いたコードは、読む人にも同じ暗記を要求します。3 か月後の自分を含め、読む人はたいてい急いでいます。
JavaScript
// 動くが、読み手に優先順位の暗記を要求する
const canPin = hasPhoto && likes >= 100 || isPinned;
// 意図が一目で分かる
const canPinClear = (hasPhoto && likes >= 100) || isPinned;実行結果はまったく同じで、速度の差もありません。違うのは読む速度だけです。レビューで「この括弧は要らない」と言われることはほとんどありませんが、「ここは括弧が欲しい」はよく言われます。迷ったら書く、で問題ありません。
他人の書いた長い式を読むときも手順は同じです。まず算術と比較のまとまりに頭の中で括弧を付け、次に && のまとまりを括弧でくくり、最後に残った || を左からつなぎます。読み解いた括弧をそのままコードに残しておけば、次に読む人の手間も省けます。
返す値の型をそろえる
&& と || が返すのは真偽値ではなく、判定に使った値そのものです。
isPinned に文字列が入っていれば、式全体もその文字列を返します。
JavaScript
const isPinned = "yes";
console.log(false || isPinned); // yes 文字列がそのまま返る
console.log(Boolean(false || isPinned)); // true 真偽値になる真偽を返すつもりの関数なら、式全体を Boolean() で包んでおくと、
呼んだ側が受け取る型が揺れません。包む位置は式の外側です。
よくある間違い
!の作用する範囲を勘違いする —!は&&や||よりずっと強いので、!hasPhoto && isPinnedは(!hasPhoto) && isPinnedと解釈されます。「写真があってピン留め、ではない」と書きたいなら!(hasPhoto && isPinned)のように括弧が必要です- 括弧を付けすぎる —
((a === 1))のような二重括弧や、(likes) >= (100)のような細かすぎる括弧は逆に読みにくくなります。まとまりの単位に 1 組だけ、が目安です
要件
- 関数名は
canShowBadge、引数はpublishedviewsisOwnerの 3 つにすること - 条件は
(published && views >= 100) || isOwnerとし、丸括弧を明示すること - 閲覧数はちょうど 100 のときも条件を満たすこと (
>=を使う) - 戻り値は必ず boolean にすること (
Boolean()で包む)
入出力例
canShowBadge(true, 120, false) → true
canShowBadge(true, 100, false) → true
canShowBadge(true, 99, false) → false
canShowBadge(false, 0, true) → true
canShowBadge() → false