prototypeの汚染と, その対策

こんにちは. 昨日のエントリのコメントで「for-inで列挙されないようにすべき」とご指摘をいただきました. それについてのまとめ.

問題

以下のようにprototype拡張を行った場合, for-in文で列挙すると拡張をおこなったプロパティも表示される.

プログラム
Array.prototype.test = function () {};
var hoge = ['a', 'b', 'c'];

for (var i in hoge) {
  console.log(i);
}
結果
0
1
2
test

配列はfor文を使うのでは

しかし, 配列を拡張する場合に限っては気にする必要はないと思う. なぜなら, 配列をfor-in文で列挙することはないから. 普通は以下のようにfor文で走査する.

Array.prototype.test = function () {};
var hoge = ['a', 'b', 'c'];

for (var i = 0; i < hoge.length; i++) {
  console.log(hoge[i]);
}

どうしてもfor-in文を使う場面がきても

どうしてもfor-in文を使うときがきても, hasOwnProperty()メソッドで防げる. for-in文を使うときはhasOwnPropery()メソッドを必ず伴うべきと「JavaScript the good parts」や「JavaScript patterns」でプラクティスとして紹介されている.

Array.prototype.test = function () {};
var hoge = ['a', 'b', 'c'];

for (var i in hoge) {
  if (hoge.hasOwnProperty(i)) {
    console.log(i);
  }
}

まとめ

配列はfor文で走査し, もしfor-in文でプロパティを列挙するときはhasOwnProperty()メソッドを伴うようにする.
ただ, 指摘いただいた通り, 無闇にpropertyを拡張するのはよくないと思う. とくにチームで開発するときはメンバーの了解を必ずとるべきだし, プラクティスの共有を日頃から行うべきだと感じました.