イベントハンドラのキャッシュをスイープしたいかもしれない。

prototype.jsは、IEメモリリークのバグに対処するために、イベントハンドラを自前でずっと持っておいて、documentがunloadされるタイミングで全部イベントハンドラを解除するようになってる。

次のようなコードを考える

Event.observe($('C'), "click", function(){...});

$('P').update("hgoe");
// ↑は $('hoge').innerHTML = "hoge"; と同じ。

一見何の変哲も無いコードだけど、イベントハンドラを登録された $('C') が $('P') の子要素だった場合、問題がある。

本来なら、 $('P') の子ではなくなって宙ぶらりんになった $('C') とそのイベントハンドラは、被参照が0になってGCのタイミングで開放される。ところが、prototypeが自前でイベントハンドラをキャッシュしているので、被参照が0にならず、ページ遷移が起こるまでずっと開放されない。

アプリケーションが、短時間で遷移が起こる作りであれば問題は無い。しかしながら、長時間に渡って使用され、かつイベントハンドラ付きのHTML片が動的に入れ替わるアプリケーションだと、死んだはずのオブジェクトがどんどん溜っていってしまう。

と、思うんだけどどうなんでしょ?

対処療法として、キャッシュをどこかのタイミングで掃除できるようなメソッドを用意するべきなんじゃないかと思う。つまり、キャッシュされているエレメントの中で、親要素が無くなってしまったものを、キャッシュから無くしてしまうようなメソッド。ただこれにも問題があって、親要素が無くなって宙ぶらりんだからと言って、被参照が0であるということにはならないという点。例えば、一時的にdocumentから外しているけど、後からまたdocument内に戻す予定でどっかに保持してあるときとかには、unloadのタイミングでイベントハンドラを解除しなくちゃいけないので、キャッシュから外されては困る。

キャッシュに登録したり解除したりするメソッドを用意しておいて、動的に変なことをやる場合にはプログラマの責任でキャッシュを操作するのが妥当なのかも。


ぶっちゃけflashアプリにすれば良いという身も蓋も無い話が正解な気もする。またいずれちゃんとデータを取ろう……。