異なる言語間で一見同じように見えても実は挙動が異なるというのはよくある話で、たとえば論理演算子 || (PHP の場合は or も同義)は、JavaScript と PHP では仕様が異なります。
サンプルコード
<script>
alert(0 || 10 || 20);
// アラート内容:10
alert(false || '' || null);
// アラート内容:null
</script>
<?php
var_dump(0 || 10 || 20);
// 出力結果:bool(true)
var_dump(false || '' || null);
// 出力結果:bool(false)
// 余談ですが、ここで echo (0 || 10 || 20); とすると 1 と出力されます。
// PHP では真偽型の true を出力しようとすると 1 に型変換されるんです。
// ちなみに false だと何も出力されません。
解説
JavaScript の論理演算子 || は「最初に見つかったtrueっぽい値」をそのまま返します。「true っぽい」とは何かについて話すと長くなりますが、0とか空文字とか null とか false とか undefined とかじゃない系の値のことです。
上記の例でいうと、最初の 0 は false っぽい(← true っぽいの逆)ので飛ばされて、2番目の b の値 10 が true っぽいので、それが返ってくるわけですね。
そして、もしどれも true っぽくない場合は、一番最後の値が返ってきます。
(上記を一言で言えば「最後に評価された値を返す」と言えます)
一方、PHPはというと、「ひとつでも true っぽいものがあったら true を返す。そうでなければ false を返す」という感じ。こっちのほうがわかりやすいかもしれません。
論理和(||)ではなく論理積(&&)だとどうなのか
もちろん、&& も || と同じくJavaScript の場合は「最後に評価された値」を返しますし、PHPの場合は真偽値を返します。
他の言語だとどうなのか
上記では例としてよくウェブ系で使われる JavaScript と PHP を使いましたが、他の言語だとどうなの?って疑問が当然出てくると思います。
結論だけ言うと、Perl とか Python とか Ruby とかは JavaScript と同じで、C とか Java とかは PHP と同じです。
もちろん、「true っぽい」の定義がそれぞれの言語で異なるので、そのあたりの違いはあります(たとえば Ruby では 0 は true っぽいほうに入ります)。
ちょっと調べてみたところ、こんな感じで、間違って説明しているサイト結構あるみたいですね。こまったものです。
使い道(JavaScript的仕様の場合)
たとえば、以下のように値が false っぽい場合に別の値を設定することができます。
<script>
function test(a) {
var hoge = a || 'default';
// 色々処理
return hoge;
}
alert(test('abc'));
// アラート内容:abc
alert(test());
// アラート内容:default
</script>
JavaScript なので 0 とかも false っぽいと判断されることは注意が必要。
厳密に undefined だけを判定してやるなら typeof a が 'undefined' と同じかどうかを判定しないといけないですね。
(typeof a === 'undefined'
と a === undefined
の違いはなにか、という話もありますが、本筋と逸れるので略)
【補足】上記の例だけだと「(PHPみたいに)引数のデフォルト値が設定できればいいだけの話じゃん」となりそうですが、|| の場合は、3つでも4つでもいくつでも「最初に true っぽいやつ」を代入できる、というのがミソです。
(ちなみに JavaScript の最新版といえる ECMA Script 6 では function hoge(foo, bar = 1) {...}
といった感じでデフォルト値を設定できるようになっていますね)
まぁ覚えていれば、そのうち役に立つことがあるかもしれないし、ないかもしれない……。
ちなみに論理演算子の結果を true か false で欲しい場合もあると思いますが、そういう場合は Boolean(a || b || c)
といった感じで真偽型に変換してやればいいだけです。
【補足】PHP 5.3 から三項演算子(式 ? 式がtrueっぽい場合の値 : 式がfalseっぽい場合の値
)の省略形「?:」が使えるようになっているらしく、これで JavaScript の || と同じことができるみたいです。例:var_dump(0 ?: 10 ?: 20)
→ int(10)