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,', ');
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,
TRY3
Object.prototype.foo = ''; Object.prototype.bar = ''; obj = { one : 1, two : 2};
Result3
IEでの結果
bar, foo, one, two,
結果
実験結果より考察するとTRY1のようにprototypeチェーンでつなげていくとprototypeチェーンにつながっている新しいほうから列挙される。TRY2とTRY3ではIEの場合では(∀`?)という結果になり。静的メソッドは最後に列挙された。
まとめ
TRY1のパターンでは for(i in Object) で break文を利用してもよさげ。TRY2だとIEとそれ以外の挙動が異なる為breakではなくcontinueを利用したほうがいい。またTRY3においても同じ結果であった為に continueを推奨します。
*1:むかしの