nulil

仕事が忙しい;;師走だから?
最近、仕事の関係でjavascrpt触ることが多くなって、ふと調べたらjavascriptのクロージャでメモリリークが簡単に発生することを知りました。
でも、古めな記事ばかりなので、最近のモダンブラウザでは対応済みかもしれません。

いくつか記事を見てたら、クロージャとメモリリークについてのコピペ – JavaScriptとかPerlとかPHPとかさくらVPSとか勉強するに、createLeakFreeClosure なるものが載ってましたが、こんなややこしいことしないと駄目なのかなぁ、と自分なりに考えてみました。
で、思い着いたのがこれ。

1 function unClosure(fn) {
2   return new Function('return function(){'
3 	+ '  return (' + fn.toString() + ').apply(this, arguments);'
4 	+ '}'
5 	);
6 }

Function.toString()から、new Function で関数を作り直してます。

一部の参照を残したいときもあるかなと思ってのver.2
with使ってるから微妙?

1 function unClosure(fn, use) {
2   return  (new Function('__with__',
3 	'with(__with__){'
4 	+ '  return function(){'
5 	+ '    return (' + fn.toString() + ').apply(this, arguments);'
6 	+ '  }'
7 	+ '}'
8 	)(use));
9 }

with使わないとこんな感じかな

 1 function unClosure(fn, use) {
 2   var k, vals = [], vars = [];
 3   for (k in use){
 4 	if (use.hasOwnProperty(k)) {
 5 	  vars.push(k + '=c[' + vals.length + ']');
 6 	  nulls.push(k + '=null');
 7 	  vals.push(use[k]);
 8 	}
 9   }
10   return  (new Function('c',
11 		'return (function(){'
12 		+ ((0 < vars.length) ? '  var ' + vars.join(',') + ';' : '')
13 		+ '  var r;'
14 		+ '  r = (' + fn.toString() + ').apply(this,arguments);'
15 		+ '  ' + nulls.join(',') + ';'
16 		+ '  return r;'
17 		+ '}.apply(this,arguments));'
18 	  )(vals));
19 }

Function.prototype.unclosure = function(){ return unClosure(this, arguments[0]); };ってしとけば

1 var img = document.getElementsByTagName('img')[0];
2 img.onclick = (function(){ alert(v); }).unclosure({v:'unclosure'});

こんな感じで使える。
変数の参照は切れたので、たぶんcreateLeakFreeClosureの代わりになるかな?
elementを変数に入れてて、それをクロージャ内で参照 って場合にちゃんとメモリリークしないかは、検証が必要そう…