javascript未解決問題(2)
ダーティーフラグ的なことを実装しようとして、前回最後のソースが出来たわけなんですが、実はしかし。元々、動いてるプログラムの改修を命じられて手を入れてたという前提があって、そのプログラムでは既にonChangeイベントでの処理をやってたんですね。
<html> <script language="javascript"> var Flag = 0; function Init() { var ObjArray = fooform.getElementsByTagName("select"); for(var idx=0,len=ObjArray.length; idx<len; idx++) // 配列にforeach文使うと駄目らしいので修正しときますね { ObjArray[idx].onchange = FlagOn; } } function FlagOn() { Flag = 1; } </script> <body onLoad="Init();"> <form name="fooform"> <select name="hoge"></select> <select name="huga" onChange="alert('Hello! Huga!');"></select> <select name="piyo"></select> </form> </body> </html>
ここでいうと、hugaというプルダウンにonChangeイベント処理が仕掛けてあったわけなんです。この場合に、例のInit()処理が走ると…。実際に試してみると判ると思いますが、元々hugaに仕掛けてあった処理が走らなくなります。
まあ、よく考えるまでもなく、Init()でのループでonChangeイベントを新しい関数で塗りつぶしてしまってるので、元々あった関数が消えてしまってたわけです。さて、既に設定されているonChangeイベントに新たな処理を追加することって出来るのでしょうか?これが今回の課題となります。
ObjArray[idx].onchange += FlagOn;
とか
ObjArray[idx].onchange.push(FlagOn);
とか闇雲に試してみましたが駄目でしたwww
まじめに調べてみると、どうもhtml内のselectタグの中でonChange="foo();"と書くと実際には
this.onchange = function anonymouse(){foo();};
ちう感じで無名関数を作ってその中に処理が展開されいるようです。そんなわけで
function Init() { var ObjArray = fooform.getElementsByTagName("select"); for(var idx=0,len=ObjArray.length; idx<len; idx++) // 配列にforeach文使うと駄目らしいので修正しときますね { var func = ObjArray[idx].onchange; ObjArray[idx].onchange = function(){ func(); FlagOn();}; } }
と、Init()処理を書き直してやればよいかと思いました。非常にキモチ悪いけど。ところがしかし!実際に試してみると、やっぱり動きません。onChange()イベントが起こった時にはfuncはnullになってしまってました。推測ですが、onchangeを書き換えたタイミングで予め作成してあった無名関数の実体が破棄されたっぽいすね。そんなわけで
var func = new Function;
とか明示的なメモリ確保とかやってみましたが、結果変わらず。関数が破棄されるのを防ぐすべはないようですね。逆に、関数の実体をコピーする方法も色々試してみましたが無理そうです。むー。どうしたものかかか。