JavaScript: 不思議な真偽値

JavaScript は, あらゆる値を真偽値判定に使えます。しかし、偽になる値は限定されています。

値または型 真偽値
undefined 偽.
null 偽.
Boolean 型 その値どおり. true は真, false は偽.
Number 型 +0, -0 および NaN は偽. その他は真.
String 型 空文字列 "" は偽. その他は真.
Symbol 型 真.
Object 型 真.

0 が偽というのは C言語っぽい。BigInt 型の 0n も "偽" になる。

空文字列が偽になる一方で, 空配列 [] は "真" になる.空オブジェクト {} も真. Common Lisp では空リストも偽になるので、JavaScript はそれとは異なる流派ということになる。

true, false との比較

真偽値の代表的な値は true, false です。これらと比較したらどうなるか。

文字列 "0" は真. 空配列も同様。でも, "0" == false もまた真になる。暗黙の型変換は意外なことが起こる。この点でも, == はもはや使ってはならない。

== true == false === true === false
undefined false false false false
null false false false false
false false true false true
true true false true false
0 false true false false
1 true false false false
NaN false false false false
Infinity false false false false
"" false true false false
"0" false true false false
"1" true false false false
[] false true false false
{} false false false false

undefined, null, NaN, "" は, 偽にも関わらず, false との比較ではイコールになりません。したがって、真偽値を確認するのに, true とも false とも比較してはいけません。

"真値" を true に, "偽値" を false に変換

Boolean() を使えばよい。あるいは, !! でもよい。

new Boolean() でないことに注意。プリミティブ値のクラスをnew するのは意味がないどころか正常にうごかないが、実行時エラーにならないので、注意するしかない。

Number() や String() に渡したら?

数値や文字列に変換するとどうなるか。

Number() String()
undefined NaN "undefined"
null 0 "null"
false 0 "false"
true 1 "true"
0 0 "0"
1 1 "1"
NaN NaN "NaN"
Infinity Infinity "Infinity"
"" 0 ""
"0" 0 "0"
"1" 1 "1"
[] 0 ""
{} NaN "[object Object]"

Number() の値が混乱している。偽値のうち undefined, NaNNaN になるのは分かる。そうであるならどうして, null が0 になるんだ。

{}NaN になる一方で, [] が 0になる。何なんだ。

parseInt(str, radix) は, また違った結果になる。null, undefined, false, "", [], {} ともすべて NaN になる。

文字列 "TRUE" または "FALSE" を真偽値に変換

いろんなやり方が考えられるが, JSON.parse() を使うのはやりすぎ。

例えば, 次のような方法が考えられる。

JavaScript
[RAW]
  1. function toBool(str) {
  2. if (str === null || str === undefined)
  3. return null;
  4. if (typeof str === "string") {
  5. switch( str.trim().toLowerCase() )
  6. {
  7. case "true": case "yes": case "1": return true;
  8. case "false": case "no": case "0": return false;
  9. default: break;
  10. }
  11. }
  12. return Boolean(str);
  13. }
  14. console.log(toBool(), toBool("True"), toBool("FALSE"), toBool("hoge"));
  15. //=> null true false true