detachEvent [JavaScript]
◆object.detachEvent メソッド
object.detachEvent(event, function)
attachEvent で登録したイベントハンドラを開放するのが、detachEvent の役割です。
attachEvent 同様、主要なブラウザの中では、Internet Explorer、Opera が対応しています。
Firefox、Safari、Google Chrome は対応していません(これらのブラウザは removeEventListener メソッドを使います)。
組み込みクラスの中で、Object クラス、HTMLDocument クラス、Element クラスなどに準備されているメソッドです。
第一引数 event はイベント名文字列(プレフィックスに 'on' を含む)、第二引数 function は登録されているイベントハンドラ メソッドです。
attachEvent と detachEvent を使うと、<body onload="hoge();"> なんていう恰好悪い書き方をしなくても、 window のロードを検知して JavaScript を起動する処理を、スマートに書くことができます。
・・・・・・なお。
detachEvent でも、解放できないイベントハンドラがあるので、注意が必要です。
【注意】:匿名関数イベントハンドラの開放について、追記があります。
こんなソースを書いてみました。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>detachEvent</title>
<script type="text/javascript" >
//<![CDATA[
// input text にメッセージ出力
function outputMessage(strMessage) {
var elm;
elm = document.getElementById('Text1');
elm.innerText = strMessage;
}
// [attachEvent イベントハンドラ] ボタンのイベントハンドラ
function onClickButton1(evt) {
var elm = document.getElementById('Button1');
elm.detachEvent('onclick', onClickButton1);
outputMessage('attachEvent イベントハンドラをデタッチしました。');
}
// [匿名関数イベントハンドラ] ボタンのイベントハンドラ
function onClickButton2(evt) {
var elm = document.getElementById('Button2');
elm.detachEvent('onclick', function () { onClickButton2(); });
outputMessage('匿名関数イベントハンドラはデタッチできません。');
}
// [HTML の onclick イベントハンドラ] ボタンのイベントハンドラ
function onClickButton3(evt) {
var elm = document.getElementById('Button3');
elm.detachEvent('onclick', onClickButton3);
outputMessage('HTML の onclick イベントハンドラはデタッチできません。');
}
// [テキストボックスのリセット] ボタンのイベントハンドラ
function onClickButton4(evt) {
outputMessage('');
}
// ウィンドウ ロード イベントハンドラ
function onWindowLoad(evt) {
window.detachEvent('onload', onWindowLoad);
var elm;
elm = document.getElementById('Button1');
elm.attachEvent('onclick', onClickButton1);
elm = document.getElementById('Button2');
elm.attachEvent('onclick', function () { onClickButton2(); });
outputMessage('Window のロードが完了しました。');
}
// ウィンドウ ロード イベントハンドラの登録
window.attachEvent('onload', onWindowLoad);
//]]>
</script>
</head>
<body>
<input id="Text1" type="text" style="width: 50%;" readonly="readonly" value="Window のロード中です。" />
<br />
<input id="Button1" type="button" value="attachEvent イベントハンドラ" />
<br />
<input id="Button2" type="button" value="匿名関数イベントハンドラ" />
<br />
<input id="Button3" type="button" value="HTML の onclick イベントハンドラ" onclick="onClickButton3();" />
<br />
<input id="Button4" type="button" value="テキストボックスのリセット" onclick="onClickButton4();" />
<br />
</body>
</html>
JavaScript の中で、window オブジェクトに対して onload イベントに onWindowLoad イベントハンドラを登録していますが、これが <body onload="hoge();"> の代わりに、window オブジェクトのロードイベントをひっかけて、JavaScript を起動する仕組みです。
window オブジェクトのロードイベントをハンドルするイベントハンドラでは、きちんと detachEvent で自分自身を開放しておきましょう。
このサンプル ソースでは、他に 3 通りの detachEvent を試しています。
ひとつめは、きちんと定義された(つまり、匿名関数ではない)関数を attachEvent したものに対して、detachEvent する例。
このケースは、attachEvent されたイベントハンドラが、detachEvent できちんと解放されます。
ふたつめは、attachEvent でイベントハンドラとして匿名関数が登録された例。
このケースでは、attachEvent で登録したイベントハンドラであっても、detachEvent で開放することはできません。→すみません、ウソでした。【追記】を参照してください。
みっつめは、HTML の onclick 属性で指定したイベントハンドラに対して、detachEvent を試みる例。
このケースでも、 イベントハンドラを detachEvent で開放することはできません。
これらの挙動は、Internet Explorer でも Opera でも同じです。
まあ、よっぽどの事情がない限り attachEvent で無名関数をイベントハンドラに登録することもないでしょうし、個人的には HTML の onclick 属性を使うのも好きではないので、あんまり問題はないんですが。
一応、「そういう挙動をするんだよ」という、備忘録代わりに記しておきます。
【追記】:2010/12/09 0:42
匿名関数イベントハンドラを開放する方法を発見しました。
// ウィンドウ ロード イベントハンドラ
function onWindowLoad(evt) {
window.detachEvent('onload', onWindowLoad);
var elm;
elm = document.getElementById('Button1');
elm.attachEvent('onclick', onClickButton1);
elm = document.getElementById('Button2');
elm.attachEvent('onclick', function () { onClickButton2(); elm.detachEvent('onclick', arguments.callee); });
outputMessage('Window のロードが完了しました。');
}
arguments.callee がキーです。
こいつは、呼び出された関数内で、その関数への参照を保持しているようです。
そのおかげで、無名関数でも、(その関数内であれば)関数を操作できるんですね。
Internet Explorer でも、Opera でも動作を確認しました。
これを attachEvent で呼び出されるイベントハンドラ側に渡してやれば、少しは構造的な仕組みで無名関数を detachEvent で開放できるかもしれませんね。
一応、テクニックとして残しておきます。
まったくわからない。
横文字が てんこ盛り並んでる。
by ゆうみ (2010-12-09 11:26)
これでお給料頂いてます、はいw。
by みみちゃん (2010-12-09 19:37)
これも語学ですよねw
フローを書いて(または場当たり仕様)、それをlanguageに展開できるようになりたい、と思ってます
by One-for-you (2010-12-10 01:46)
語学ですね。
俺の哲学は「日本語が喋れるならプログラムを書ける」です。
by みみちゃん (2010-12-10 20:47)