相互参照は、スクリプトを作成するときに作成されます。たとえば、次のコードです:
window.onload = function () {
var x = document.getElementsByTagName('H3');
for (var i=0;i{
x[i].onclick = openClose;
x[i].popularElement = x[i].nextSibling; // 簡略化された状況
x[i].関連付けられている要素 = x[ i];
}
}
または、スクリプト言語で最も一般的なクロージャであるクロージャを関数で使用する場合、IE はメモリを再利用できません。閉じた文は、DOM オブジェクトのイベント ハンドラーを登録するときに最も一般的に使用されます。 Novellborn は、このバグを実行して実際に感じることができるいくつかの例を提供しています。
私のお気に入りの QuirkMode は、昨年初めにこのバグに大きな危険が潜んでいることに気づき、Web 開発者に注意を払い、この問題を回避するために最善を尽くす必要があると感じ、全員を奨励するためにチャリティー招待コンテストを開催しました。独自の addEvent/removeEvent ソリューションを送信します。そして昨年 10 月下旬、最終的に彼らが検討した勝者を発表しました。John Resig です。John が勝者となるコードは次のとおりです:
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e' type fn] = fn;
obj[type fn] = function(){obj['e' type fn]( window.event );}
obj.attachEvent( 'on' type, obj[type fn] ); 🎜>} else
obj.addEventListener( type, fn, false );
}
function RemoveEvent( obj, type, fn ) {
if ( obj.detachEvent ) {
obj. detachEvent( 'on ' type, obj[type fn] );
obj[type fn] = null;
obj.removeEventListener( type, fn, false ); >
John を勝者として選択するための QuirkMode の説明を要約すると、上記のコードが最も簡潔で効果的であると同時に、メモリの問題を回避しながら、このキーワードが IE のattachEvent で正常に動作することも賢明に保証されています。もちろん、欠点はまだ存在します。
Netscape 4 および Explorer 5 Mac はサポートされていません。 (国内のプログラマは冷笑するかもしれませんが、海外は広範な互換性を重視しています)removeEventでは
remove obj["e" type fn]が省略されています。
要するに、何があってもシンプルなものが勝つのです。
結果が出るやいなや、多くの出場者やコメンテーターは納得せず、すぐに John のコードのいくつかの問題点を指摘しました:
AddEvent 自体は閉じた文を使用しているため、IE の問題を根本的に解決するものではありませんメモリリークの問題。
IEで同じ種類のイベントが繰り返し登録され、繰り返し実行される場合がある問題は解決しておりません。
その後、数人の専門家が改善された解決策を提案しました:
コードをコピーします
Scott Andrew LePera、Dean Edwards、Peter-Paul Koch によって調整
Tino Zijdel によって IE 用に修正 (鮮明)
IE ではこれに注意してくださいメモリ リークが発生し、W3C イベント モデルをサポートするブラウザとまったく同じように機能しません。
- イベントの実行順序が同じではありません (FIFO に対する IE の LIFO)
- に関連付けられた関数同じ要素の同じイベントが複数回実行されると、IE でも複数回実行されます。
*/
function addEvent( obj, type, fn ) {
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent) {
obj["e" type fn] = fn;
obj.attachEvent( "on" type, function() { obj[ "e " type fn](); } );
}
}
function RemoveEvent( obj, type, fn ) {
if (obj.removeEventListener)
obj.removeEventListener( type , fn , false );
else if (obj.detachEvent) {
obj.detachEvent( "on" type, obj["e" type fn] ); = null ;
}
}
明らかに、John のコードのいくつかの欠点は修正されています。ただし、メモリリークは依然として存在し、一部のブラウザはまだサポートしていないため、IE の重複登録は避けられません。さらに、コメントによると、複数のイベント ハンドラーが同じオブジェクトに登録されている場合、IE と他のブラウザーの実行順序が異なり、これも隠れた危険です。
数日後、最も厳格と考えられる計画がディーン・エドワーズによって提案されました。 Dean の解決策は異なります。
オブジェクト検出を実行しません
addeventListener/attachEvent メソッドを呼び出しません
このキーワードを正しいコンテキストで実行し続けます
イベント オブジェクト パラメーターを正しく渡します
完全にこれまでのところクロスブラウザー (IE4 と NS4 を含む)
メモリ リークはありません
ディーンのコードは次のとおりです:
コードをコピー