Boring Days as tech

金に生きるは下品にすぎる、 恋に生きるは切なすぎ、 出世に生きるはくたびれる。 とかくこの世は一天地六。 命ぎりぎり勝負をかける。 仕事はよろず引き受けましょう。 大小遠近男女は問わず、委細面談、仕事屋稼業。

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は連想配列に対して行うということですね。