Arrayを__proto__で機能拡張したときのfor inの注意点
昔書いてたメモ。
たとえばArrayオブジェクトを以下のように拡張する。
すると普通にArrayオブジェクトからemptyメソッドが使えるようになる。
Array.prototype.__proto__ ={ empty : function(){return "emptyが呼ばれたよ!";} } var ary = []; alert(ary.empty()); //"emptyが呼ばれたよ!"
そしてfor inをしたときには以下のようになる。
Array.prototype.__proto__ ={ empty : function(){return "emptyが呼ばれたよ!";} } var ary = ["1","2","3"]; var str = ""; alert(ary.length); // "3"←3つの値を配列として保持させたのでlengthは勿論3となる for(var i in ary){ str += i; } alert(str); // "012empty"←lengthが3なので"012"となることを期待したが…
このようにlengthは初期化した時の3のままなのに、
何故か4つめが存在していてしかもその4つめが拡張したemptyとなっている。
これはjavascriptの以下の性質の為と思われる。
var obj ={ test0 : "", test1 : function(){}, test2 : function(){} } var str=""; for(var i in obj){ str+=i; } alert(str); // "test0test1test2"←オブジェクトも連想配列として認識する為にobj配下にあるプロパティを呼んでいる。
このようにjavascriptのfor in文はオブジェクト配下のプロパティすべてを走査するため、
__proto__による拡張したメソッドまでループの中で呼び出されてしまう。
まあfor..inは連想配列に対して行うということですね。