JSLintオプション考察「unfiltered for in」

2013年07月17日

カテゴリー:

JavaScriptであるオブジェクトのプロパティを列挙するにはfor-inループを使用します。この時列挙されるプロパティには、プロトタイプ連鎖から来たプロパティも含まれることに注意しなければなりません。

プロパティを列挙する際、そのプロパティが(for-inループの対象となる)オブジェクト自身が持つプロパティなのか、それともプロトタイプ連鎖から来たプロパティなのかを判別するには、hasOwnProperty()を使用します。

JSLintでは、for-inによってプロパティを列挙する際、hasOwnPropertyを使用してプロパティのチェックを行わないと「The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.」という警告が出てしまいます。
英語にはかなり自信がないのですが、多分「for-inループ内では、プロトタイプ連鎖から来た不要なプロパティを除外するために、ifステートメントを使用すべきだ」みたいな事を言っているんだと思います。

次のコード例は、hasOwnProperty()を使用して列挙するプロパティをフィルタした例とフィルタしない例です。フィルタしない方ではJSLintで警告が出ます。

(function () {
    "use strict";

        //Parsonコンストラクタ定義
    var Parson = function () {},

        //Parsonコンストラクタから新たにオブジェクトを作成
        taro = new Parson(),

        prop = "";

    //Parsonコンストラクタにtalk関数を追加
    Parson.prototype.talk = function () {
        window.console.log("My Name is " + this.name);
    };

    //taroオブジェクトに独自のプロパティ(name)を割り当てる
    taro.name = "Taro Yamada";



    //1.フィルタしないfor-inループ
    for (prop in taro) {
        window.console.log(prop + ":" + taro[prop]);  //※警告:The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.
    }

    /*
    コンソールの表示結果
    name: Taro Yamada
    talk: function() {...}
    (talkはtaroオブジェクト独自のプロパティではないので、除外されるべき)
    */

    //2.hasOwnPropertyでフィルタされたfor-inループ
    for (prop in taro) {
        if (taro.hasOwnProperty(prop)) {
            window.console.log(prop + ":" + taro[prop]);
        }
    }

    /*
    コンソールの表示結果
    name: Taro Yamada
    */

}());

上記のコード例では、Parson というコンストラクタ関数のプロトタイプに talk という関数を追加していますので、Parsonコンストラクタ関数を使って作成されたオブジェクトは全て talk関数を持つことになります。

ここでは、Parsonコンストラクタ関数を使って taro というオブジェクトを作成し、さらにこの taro オブジェクトに対し、独自のプロパティ name を割り当てています。

この taro オブジェクトに対して for-inループを適用すると、name, talk という2つのプロパティが列挙されますが、talk プロパティ(関数、またはメソッド)は taro オブジェクト独自のプロパティではなく、プロトタイプ連鎖から来たものなので、ここでは除外しておいた方が良いでしょう。そこで、36行目の様に hasOwnProperty() でプロパティのフィルタリング処理を入れれば、ループ対象オブジェクト独自のプロパティのみ表示させることが可能になります。


通常、for-inループによりオブジェクトのプロパティを評価するようなケースでは、プロトタイプ連鎖から来たプロパティは不要である場合が多いため、JSLintにおいてこのオプションはデフォルト(false)のままで良いと思います。

JSLintのオプション一覧ページへ