2010/04/02

[javascript]true or false

このエントリーをはてなブックマークに追加
// ①
if (value) {
// 処理
}

// ②
if (value == true) {
// 処理
}

ある日ふと、上記①②の結果が異なることに気づく。
勝手にキャストされるんでしょ?と横柄にも思っていたけれど、どうもそうではないらしい。
当たり前だけど、数値⇔文字が自由に行き来するからといって、全ての型がそういうわけでもないのです。

どういう挙動なのだろうと不信に思ってしまったので、いろんな型の判定について調べてみる。
対象とするのは、undefined、null、数値(1、123、0、NaN)、文字("abc"、"1"、"123"、"0"、"")、日付、論理値(true、false)、オブジェクト型、配列、関数です。

テスト結果。


まとめ


  • 前述の通り、if(value)と(value==true)は結果が異なる。一致させるためには、Boolean(value)を使って明示的にキャストする必要がある。

  • if(value)がfalseになるのは、null、undefined、0、NaN、""、falseのとき。これは基本。

  • テスト内容とは関係ないけれどtypeof(null)はobjectになる。nullはobject。

  • (value == null)がtrueになるのは、null、undefinedのみ。

  • (value == true)と(value == 1)が一緒。

  • (value == false)と(value == 0)が一緒。(value == "")はvalue="0"のとき以外は一緒。

  • (value == true)と(value != false)は一致するとは限らない。true/falseと1/0などの論理値以外はあやしい。

  • 文字列の"true"は、Booleanとして自動的にキャストされたりしない。通常の文字列と同じ扱い。

  • 文字列の"0"は、数値にキャストされて、(value==false)と(value==0)にtrueを返す。(この辺がややこしい)

  • 配列が空かどうかが(value == false)で判別できる。if(value)は配列数に限らずtrueになる。

  • isNaNの挙動もよくわからん。objectや関数でtrueになるのはなんだろう。


論理値の挙動については、いまいち感覚的に理解しにくい印象です。
型の指定がないのをいいことに、混在させまくる利用は、コードが煩雑になることが避けられない気がします。やっぱりきっちり管理したほうが楽かも。

テストコード


以下、テストに使ったコードのベース。
実際はtrueになったところに色をつける処理を足しています。
var undef;
// undefined;
var list =
{
_undefined : undef, _null : null, _int_1 : 1, _int_123 : 123, _int_0 : 0, _nan : Number.NaN, _str_abc : "abc",
_str_1 : "1", _str_123 : "123", _str_0 : "0", _str_null : "", _str_true : "true", _bool_true : true,
_bool_false : false, _obj : {}, _array_null : [], _array_1 : [1], _func : function () {}
}
document.write("<table>");
document.write("<tr>");
document.write("<th>key</th>");
document.write("<th>typeof(value)</th>");
document.write("<th>value</th>");
document.write("<th>if(value)</th>");
document.write("<th>Boolean(value)</th>");
document.write("<th>value==true</th>");
document.write("<th>value==false</th>");
document.write("<th>value==1</th>");
document.write("<th>value==0</th>");
document.write("<th>value==null</th>");
document.write("<th>value==\"\"</th>");
document.write("<th>isNaN(value)</th>");
document.write("</tr>");
for (var key in list)
{
var value = list[key];
var r = false;
if (value) {
r = true;
}
document.write("<tr>");
document.write("<td>" + key + "</td>");
document.write("<td>" + (typeof (value)) + "</td>");
document.write("<td>" + value + "</td>");
document.write("<td>" + r + "</td>");
document.write("<td>" + Boolean(value) + "</td>");
document.write("<td>" + (value == true) + "</td>");
document.write("<td>" + (value == false) + "</td>");
document.write("<td>" + (value == 1) + "</td>");
document.write("<td>" + (value == 0) + "</td>");
document.write("<td>" + (value == null) + "</td>");
document.write("<td>" + (value == "") + "</td>");
document.write("<td>" + (isNaN(value)) + "</td>");
document.write("</tr>");
}
document.write("</table>");

2 件のコメント :

  1. isNaN Not a Number こいつ数値じゃないぞ!

    返信削除
  2. >匿名さん
    そりゃそうですよね。失礼しました。
    isNaN(null)→falseのほうを注意するべきですね。

    返信削除