JavaScriptでクロージャ
f1 = function(){return 1;}; f2 = function(){ return 3+f1();}; f1 = function(){return 10;}; f2(); 13
クロージャとして使うにはf2を定義したときその環境(=ここではf1の定義)を引きずって欲しいわけだからこれは意図した結果ではない。
f1 = function(){return 1;}; f2 = function(){ return (function(f){return 3+f();})(f1);}; f1 = function(){return 10;}; f2(); 13
これもだめ
f1 = function(){return 1;}; f2 = (function(f){return (function(){return 3+f();}) })(f1); f1 = function(){return 10;}; f = function(){return 20;}; f2(); 4
これでようやく意図した結果になった
関数は評価される時点のものが使われるようだ
↑これがないと関数の動的な書き換えができないわけで。
三番目ではf2の定義時のf1はfのスコープ(=引数のスコープ)に限定されるので外部から変更は不可能になる。
要するに関数を返す関数が必要になるってこと
スコープの問題なので
f1 = function(){return 1;}; (function(){ var f = f1; f1 = function(){return 3+f();}; })(); f=function(){return 20;}; f1();
これでもいい。finalとthisがついたらjavaでよく見る形だ
f1={foo :1, fun : function(){return this.foo} }; f2 = (function(f){return (function(){return 3+f.fun();}) })(f1); f1.foo = 10; f2(); 13
さっきの成功例と形は同じだが…
オブジェクトは参照渡しなので当然こうなる。
(ただしプリミティブなデータは値渡し)
f1={foo :1, fun : function(){return this.foo} }; f2 = (function(f){return (function(){return 3+f.fun();}) })(eval(uneval(f1))); f1.foo = 10; f2(); 4
ディープコピーをしてやる。
unevalはfirefox固有かも。