2013年5月30日木曜日

phiさん( @phi_jp )のブログ(TM Life)の以下の投稿を読んで。

JavaScriptのObjectにはlengthがない!!

オブジェクトに列挙可能ではないプロパティがある場合についてちょっと気になったので、列挙可能ではないプロパティがあるオブジェクトについてもプロパティの数が数えられるようなものを、getOwnPropertyNamesを使って書いてみた。

まず、列挙可能ではないプロパティをもつオブジェクトで、上記の記事中の関数や、コメントのObject.keys(object).lengthを使った場合。

コード(BBEdit)

function getPropertyNum(obj)
{
    var len = 0;
    
    for (var key in obj) { ++len; }
    
    return len;
}
var result = "",
    o1 = {a:1, b:2},
    // o1と同じ内容のオブジェクトを他の方法で定義
    o2 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:true},
    }),
    // bを列挙可能ではないプロパティにする
    o3 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:false}, 
    });
    // デフォルトではenumerableはfalse
    o4 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2},
    }),
    result = "プロパティの数\n" +
             "方法1: getPropertyNum\n" +
             "o1: " + getPropertyNum(o1) + "\n" +
             "o2: " + getPropertyNum(o2) + "\n" +
             "o3: " + getPropertyNum(o3) + "\n" +
             "o4: " + getPropertyNum(o4) + "\n" +
             "方法2: Object.keys(o).length\n" +
             "o1: " + Object.keys(o1).length + "\n" +
             "o2: " + Object.keys(o2).length + "\n" +
             "o3: " + Object.keys(o3).length + "\n" +
             "o4: " + Object.keys(o4).length + "\n";
$('#pre0').text(result);


どちらの方法も、列挙可能ではない(for/in ループで列挙されない、enumerableがfasle) プロパティが数えられない。

ということで、列挙可能ではないプロパティも含めたプロパティの数を調べたいときには、Object.getOwnPropertyNames()でプロパティ名の配列を取得して、その長さを調べればいい。(ただし、この方法は継承されたプロパティは含まれない。)この場合はオブジェクトo3、o4のプロパティの数はオブジェクトo1、o2と同様に2になる。

コード(BBEdit)

var o1 = {a:1, b:2},
    // o1と同じ内容のオブジェクト他の方法で定義
    o2 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:true},
    }),
    // bを列挙可能ではないプロパティにする
    o3 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:false}, 
    });
    // デフォルトではenumerableはfalse
    o4 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2},
    }),
    result = "o1: " + Object.getOwnPropertyNames(o1).length + "\n" +
             "o2: " + Object.getOwnPropertyNames(o2).length + "\n" +
             "o3: " + Object.getOwnPropertyNames(o3).length + "\n" +
             "o4: " + Object.getOwnPropertyNames(o4).length + "\n";
$('#pre1').text(result);


ちなみに、プロパティを持っているかどうかを調べたい場合も同様に、for/inループを使うと列挙可能かどうかが関係してくる。なので、列挙可能ではないプロパティも含めて、あるオブジェクトがあるプロパティを持っているかどうかは、obj.hasOwnProperty(name)を使って調べればいい。(ただし、この方法も継承されたプロパティは含まれない。)

コード(BBEdit)

var o1 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:true},
    }),
    // bを列挙可能ではないプロパティにする
    o2 = Object.defineProperties({}, {
        a: {value:1, enumerable:true},
        b: {value:2, enumerable:false}, 
    }),
    result = "オブジェクトo1とo2がプロパティbをもつかどうか\n" +
             "o1: " + o1.hasOwnProperty("b") + "\n" +
             "o2: " + o2.hasOwnProperty("b") + "\n",
    i, max;
    // for/inループで調べてもbは列挙されないからfalseになる
    result += "for/inループでo2がプロパティaとbをもつかどうか調べた場合\n";
    for (var prop in o2) {
        if (prop === "a") {
            result += "aをもつ\n";
        }
        if (prop === "b") {
            result += "bをもつ\n";
        }
    }
$('#pre2').text(result);








						

0 コメント:

コメントを投稿