読者です 読者をやめる 読者になる 読者になる

Object#hasOwnProperty() break? continue?

Objectの要素を列挙するときfor(i in Object);ループをつかったりするのですが、prototype.js*1などによるObject汚染(いい言葉ではないな)がありその回避手段としてObject#hasOwnPropertyを使ったりしますが今回は、そのループ内でhasOwnPropertyをつかったとき break と continueどちらを利用したらいいのかという実験。
breakをするとそれ以降のループが中断されるのでbreakした以降に自信のオブジェクトが出てきたら困る。安全策としてはcontinueで毎回チェックするというもの。ただprotoptypeチェーンに繋がっているメソッドやプロパティの分だけループするからお世辞にもいいとはいえない。

具体的には

●break
for(i in obj)
{
    if(!obj.hasOwnProperty(i)) break;
    // なにか処理をする
}

●continue
for(i in obj)
{
    if(!obj.hasOwnProperty(i)) continue;
    // なにか処理をする
}

どちらがより適当かということ?

TRY1

Foo = function(){};
Foo.prototype =
{
    one : 1, two : 2, three : 3
}

Bar = function(){};
Bar.prototype = new Foo();
Bar.prototype.prop1 = 1;
Bar.prototype.prop2 = 2;
Bar.prototype.prop3 = 3;

Obj = function(){};
Obj.prototype = new Bar();
Obj.prototype.method1 = function(){};
Obj.prototype.method2 = function(){};
Obj.prototype.method3 = function(){};

obj = new Obj();

for(i in obj)
	document.write(i,', ');
Result1(IE, Firefox, Opera)

method1, method2, method3, prop1, prop2, prop3, one, two, three,

TRY2

Foo = function(){};
Foo.prototype =
{
    one : 1,
    two : 2,
    three : 3
}

Bar = function(){};
Bar.prototype = new Foo();
Bar.prototype.prop1 = 1;
Bar.prototype.prop2 = 2;
Bar.prototype.prop3 = 3;

Obj = function(){};
Obj.prototype = new Bar();

obj = new Obj();
obj.method1 = function(){};
obj.method2 = function(){};
obj.method3 = function(){};

for(i in obj)
	document.write(i,', ');
Result2
IEでの結果

three, two, one, prop1, prop2, prop3, method1, method2, method3,

Firefox, Operaでの結果

method1, method2, method3, prop1, prop2, prop3, one, two, three,

TRY3

Object.prototype.foo = '';
Object.prototype.bar = '';
obj = { one : 1, two : 2};
Result3
IEでの結果

bar, foo, one, two,

Firefox, Operaでの結果

one, two, foo, bar

結果

実験結果より考察するとTRY1のようにprototypeチェーンでつなげていくとprototypeチェーンにつながっている新しいほうから列挙される。TRY2とTRY3ではIEの場合では(∀`?)という結果になり。静的メソッドは最後に列挙された。

まとめ

TRY1のパターンでは for(i in Object) で break文を利用してもよさげ。TRY2だとIEとそれ以外の挙動が異なる為breakではなくcontinueを利用したほうがいい。またTRY3においても同じ結果であった為に continueを推奨します。

*1:むかしの