LoginSignup
20
20

More than 5 years have passed since last update.

Prototype汚染に負けないfor in文の書き方

Last updated at Posted at 2015-04-23

※そもそもPrototype汚染をやめる、という話は別の機会に。

汚染された状態でも for in文を書きたい人向けです。

プロトタイプ汚染とは

Object.prototype.myMethod を拡張すると、
for in ループで myMethod が(意図せず)列挙されてしまいます。これが汚染です。

[参考]プロトタイプ汚染とループ

汚染対策

①for inをやめる:Object.Keys

※for in文の書き方とか言っておきながら、いきなりやめます(`・ω・)☆

for inをやめると、汚染されたプロトタイプ拡張で追加された
methodを呼び出すことはなくなります。わぁい。

というわけで、Object.Keysを使います。

Object.Keys
Object.keys(obj).forEach(function (p) {
  //do something
})

これで連想配列を安全に振り回せます。

ただし、これは、EcmaScript5で策定されたものです。
対象ブラウザ:http://kangax.github.io/compat-table/es5/#Object.keys

IE9から/(^o^)\
サポートブラウザをIE9としていたとしても
心の底では出来る限りサポートブラウザを増やしたい。。。。

②for inをやめたくない時:hasOwnProperty

※①をそう簡単に出来ないという場合(本題)
IE7とか8もまだサポートしたい\( 'ω')/ウオオオオアアアアーーーーーッ!!!となったら…

毎回if文を書きたくない場合はもうすこし考えます…

hasOwnProperty
for (var p in obj) {
  if (obj.hasOwnProperty(p)) {
    //do something
  }
}

他にもいろいろあるみたい。

prototype汚染問題でhasOwnPropertyを使わないクロスブラウザな方法
いちいちhasOwnPropertyを使わなくてよくする(ジェネレータの使いかた)

まとめ

  • 軽い気持ちのprototype拡張は汚染を招く
  • 考えての拡張は汚染じゃない。汚染じゃないからやっても良い
  • というかES5からは拡張しても安全になりつつある
  • ES5の関数を使うならIE8,7は切ろう
  • 汚染が起きても大丈夫なようにfor inを使うならhasOwnPropertyなどを使おう
  • もしくはObject.Keysを使う
  • hasOwnPropertyとObject.Keysで一部違いがあるのはちゃんと把握していた方が良さそう

for-inとObject.keysの違いを正しく知る
→実装のパターンなどがあるので時間があるとき読むと◎です

20
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
20