ActiveXObjectとスクリプトエンジン間の循環参照によるメモリリーク
IE6 SP2- の ActiveXObject 周りのメモリリーク問題はあまり知られていないような気がしたので、簡単にまとめておきます。
jQuery や prototype.js では以下の方法で回避しています。
/** * メモリリークを回避する方法 (jQuery および prototype.js 方式) */ function empty () { // この関数は何も実行せず、何も参照しない位置に置く。何も参照しない故に循環参照しなくなる。 } function get (url) { var xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0'); xhr.onreadystatechange = function () { // この関数は xhr を参照可能→循環参照している if (xhr.readyState === 4) { xhr.onreadystatechange = empty; // xhr を参照不可能な empty を代入したので循環参照しなくなる } }; xhr.open('GET', url, false); xhr.send(null); } get('/');
上記をもう少し簡単にしたコードがこちら。
/** * メモリリークを回避する方法 (new Function 方式) */ function get (url) { var xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0'); xhr.onreadystatechange = function () { // この関数は xhr を参照可能→循環参照している if (xhr.readyState === 4) { xhr.onreadystatechange = new Function; // Function コンストラクタによって生成されたオブジェクトは xhr を参照不可能なので循環参照しなくなる } }; xhr.open('GET', url, false); xhr.send(null); } get('/');
jQuery 方式では function empty の位置が重要で書き方を間違えると循環参照してしまいます。
new Function 方式では空の関数をその場で生成するので、置き場所に悩まなくて済みます。