JavaScriptでのnull(undefined)チェック

 至るところで使われる、nullチェックの書き方をJavaScript的に考えてみることにします。

スポンサーリンク
rectangle

nullチェックとは

 プログラミングでは、よくnullという概念が用いられています。「何もない」という特殊な値ですが、実際には、これがしばしば悪さをすることになるのです。

Javaの例

 以下のコードは実行時例外(NullPointerException)になります。

public class Main{
    public static void main(String[] args){
        boolean result = isExample(null);
        System.out.println(result);
    }

    private static boolean isExample(String s){
        return s.equals("example");
    }
}

 これは、String型宣言が行われているにも関わらず、nullという特別な値が入っているために、equals()メソッドへの参照を取得することができません。よって、アプリケーションは処理を継続する術を持たず、例外が出てしまうわけです。

 しかし、これを回避する手段があります。それが俗に言う「nullチェック」です。以下のコードを実行してみましょう。

public class Main{
    public static void main(String[] args){
        boolean result = isExample(null);
        System.out.println(result);
    }

    private static boolean isExample(String s){
        if(s == null){
            return false;
        }else{
            return s.equals("example");
        }
    }
}

 これで、nullがあっても正しくresultが返るようになりました。

 このif(s == null)の部分が、nullかどうかをチェックする、「nullチェック」と呼ばれるコードです。

JavaScriptでのnull

 JavaScriptには、nullに加えてundefinedという値があります。両者は似たようなものですが、undefinedはその名のとおり、「未定義」の値です。たとえば・・・。

var str;
console.log(str);   // undefined

 undefinedは値の内容が存在しないときに暗黙的に設定される値です。対して、nullはプログラマが明示的に設定しなければ存在しない値です。たとえば次のコードではnullが代入されます。

var str = null;
console.log(str);   // null

 nullは、undefinedを返す場合とで明示的に動作を変えたい場合などに使われますが、意識して使うケースは通常そう多くありません。

 今回は、そんなJavaScriptで使えるnull(undefined)チェックの手段について、いくつか考えてみましょう。

JavaScriptでのnull(undefined)チェック

if文で分岐する

 最も単純な例です。

var o;
if(o === undefined || o === null){
    console.log("o is null or undefined");
}

 特に理由がなければこれで問題ありません。実際には、これをこのまま使わず、ユーティリティ的なメソッドを定義して使うことになるかと思います。

function isNullOrUndefined(o){
    return (o === undefined || o === null);
}

typeof演算子を使う

 時に、ローカル変数のundefinedを上書きする悪いヤツがいるかもしれません。ES5では、グローバルのundefinedの書き換えは行うことができませんが、ローカル変数のundefinedにundefined以外を定義することができます。

 しかし、通常、クロージャ内部のローカル変数まで弄られる心配をする必要はありません。これらは良くない例として覚えておきましょう。

 たとえば以下のようなケースを考えてみます。

var result = isNullOrUndefined("example");
console.log(result);    // falseを期待するがtrueが返る

function isNullOrUndefined(o){
    var undefined = "example";
    return (o === undefined || o === null);
}

 こういったことが想定される場合、以下のようにtypeof演算子を使うことで確実性を保つことができます。

var result = isNullOrUndefined("example");
console.log(result);    // false

function isNullOrUndefined(o){
    var undefined = "example";
    return (typeof o === "undefined" || o === null);
}

 ちなみに、nullに対して値を代入しようとすると、SyntaxErrorとなりますので、こちらは心配する必要はありません。

グローバル変数を見る

 先ほどの例だと、ローカル変数のundefinedを参照してしまって期待した結果が得られませんでした。

 ES5では、グローバルのundefinedを書き換えることはできませんので、以下のようなコードでも確実性を担保できます。

var result = isNullOrUndefined("example");
console.log(result);    // true

function isNullOrUndefined(o){
    var undefined = "example";
    return (o === function(){}.undefined || o === null);
}

 なかなかトリッキーなコードです。可読性を損なうので、実際には使わないようにしましょう。

暗黙的キャストを利用する

 JavaScriptは、どのようなオブジェクトであっても、評価時に暗黙的にbooleanにキャストするという特徴があります。以下のコードを見てください。

var a = "";
var b = 0;
var c = undefined;
var d = null;
var e = NaN;

 これらは、全て暗黙的にfalseと評価されます。これを利用すれば、簡単にnullチェックが実現できます。しかしこれは、限られた用途にしか使えないことを覚えておいてください。入力がNumber型やString型の場合、空文字や0、NaNもfalseと評価されてしまうことに注意しましょう。

 以下のように、入力値がいくつかのケースに限られている場合に有効でしょう。

var o = findById(1);

if(o){
    console.log(o.name);
}

function findById(id){
    if(id === 1){
        return {
            id: 1,
            name: "example"
        };
    }
    return null;
}

 oがnullの場合は、consoleを表示しないのでo.nameが評価されません。仮にoがnullなのにo.nameを評価しようとした場合、TypeErrorが発生してしまいます。このコードは、これを未然に防いだものです。

配列などのケース

 ところで、配列などに対してforEachメソッドを実行したい場合に、nullチェックを行うケースがあります。

var arrays = getArrayOrNull();

arrays.forEach(function(arr){
    console.log(arr);
});

// ランダムでnullかArrayを返すメソッド
function getArrayOrNull(){
    return Math.round(Math.random()) ? [1,2,3] : null;
}

 これをこのまま実行すると、50%の確立でTypeErrorが発生しますが・・・。

 以下のようにすれば、nullの場合は空配列を代入するため、問題なく動作します。

var arrays = getArrayOrNull() || [];

arrays.forEach(function(arr){
    console.log(arr);
});

// ランダムでnullかArrayを返すメソッド
function getArrayOrNull(){
    return Math.round(Math.random()) ? [1,2,3] : null;
}

 これもよく使われるテクニックです。適切な場所で使えると簡潔ですね。

まとめ

 いろいろ手段はありますが、通常のコーディングでは最も単純な厳密等価演算子を使うのがベターでしょう。

 しかし、暗黙キャストを使う方法も、よく使われています。ケースによって適切な使い方をして、バグなく可読性に優れたプログラミングを行いたいものですね。