はてなマップの prototype.js による Object.prototype 汚染の弊害

以前からprototype.jsでObject.prototypeが汚染されてしまうのは問題になっていた。詳しくはノゾキ日記アルファニート2.0の人がまとめている。先日はてなマップが正常に動かなくなったときいて、そういやはてマってprototype.jsつかってるからそのせいじゃないかな、と思って昼間検証したところ(有休バンザイ!)ドンピシャだった。

で、Rails追っかけやprototype.js追っかけの人は知ってると思うんだけど、最近のprototype.js(prototype.js 1.4.0_preからかな?)ではこのObject.prototype汚染がマズイと思ったのか、Object.prototype拡張がなくなった。そのため、継承は以前では

ExtendKlass.prototype = (new Klass).extend({});

と書かれていたのが、

ExtendKlass.prototype = Object.extend(new Klass, {});

とObject.extend(Object.prototype.extendでは無い)を使った方法に統一されるようになった。こちらのほうが記述コストはかかるのだが、Object.prototypeが汚染されるよりはいいよね。最近ずっとこっちの書き方で慣れていたのではてマのjsのソースを見たときに違和感が…。

なのではてマで使われているjsの継承方式をObject.extendを使う方法に変更し、prototype.jsを最新の1.4.0_pre7に変更したところ、いぜんの正常なはてマの挙動に戻った。

Object.prototype汚染がマズイマズイ云われていたけど、大きい商用サイトじゃ初めて実際問題にぶちあたったよなぁ。これでいろんなJavaScript使いの人にObject.prototype汚染の怖さを認識してもらえそうだ。

で、思ったのがやっぱりJavaScriptできちんとテスト書くのって難しそうだなぁ、と。今回起きる問題の再発防止のためにJavaScriptでテスト書いてください、つわれても俺書けないよ。書けたとしてもテスト書くのにコストかかりすぎそう。実際のブラウザを介してやるseleniumだとマウスクリック時の挙動とか書けないし。onClickとかってfunctionとして呼び出すことできたんだっけ(調べてない)。