2011年10月18日

javascript:関数で別の関数をクロージャ化してローカル変数を与える

関数をクロージャ化してローカル変数を与えてみる。
※ ローカル変数云々というより、関数を encloser でラップして、スコープチェーンを encloser につなげるって言った方がいいのかな。(同日追記)

function f(){
  alert(v);
}


辿れるスコープ内に v という変数が無ければ、v は当然 undefined。
で、以下の関数。

function encloser(){
  eval('var ' + arguments[1] + ' = "' + arguments[2] + '";');
  return eval('arguments[0] = ' + arguments[0]); // ※ () 追加では ie が ng
}

※ とりあえず string のみ対応。json 化すれば object でも。

この encloser関数にさきほどの f関数を渡してやると……。

f = encloser(f, 'v', 'I am closer!');
f(); // I am closer!


v に値が入れられる。



 こんなもん何に使うんだろ?

こんなもん何に使うんだ? と聞かれたら、情報弱者な私は「さぁ?」と言う。思いついたは良いが、多分どっかに有用な情報があり、体系的に述べられているだろう。とはいえ「eval クロージャ」でググっても大した情報が見つけられなかった(※ ざっと見)。なので、自分で考えてみる。

global を汚さず関数内に静的変数を疑似的に作るなら。クロージャなんぞ使わずに、

function func1(){
  func1.value = func1.value || 0;// 初期値
  alert(func1.value++);
}


func1(); // 0
func1(); // 1
func1(); // 2


でいいんじゃね? と思う。関数内で関数名を使っているので抽象度が低い。あとは当然、関数外から func1.value を参照&変更できる。

 じゃあ。あれだ。parent キーワードがいい

function inherits(o){
  var f = function (){};
  f.prototype = o;
  return new f();
}


というプロトタイプチェーンの繋がったオブジェクトを生成する関数。

function inherits(o){
  var f = function (){};
  f.prototype = o;
  (f = new f()).parent = o;
  return f;
}


とでもすれば、this.parent で、親オブジェクトが簡単に参照できる。けども……。this. と付けるのすらメンドクセーってことないかな。自分は大いにメンドクサイ。例えば、普通なら作られたオブジェクトに extend({...}) のような感じでメソッド追加してゆくのだろうけども、その中でやれば……。

var lib = {
  name : 'lib',
  ext : function (){
    var parent = lib;
    for(arguments[1] in arguments[0]){
      this[arguments[1]] = arguments[0][arguments[1]];
      if(typeof(this[arguments[1]]) == 'function'){
        eval('this[arguments[1]] = ' + this[arguments[1]]);
      }
    }
  }
};


var obj = inherits(lib);
obj.ext({
  name : 'obj',
  fnc1 : function (){return this.name;},
  fnc2 : function (){return parent.name;},
  fnc3 : function (){return this.parent.name;} // 順当な方法?
});


console.log(obj.fnc1()); // obj
console.log(obj.fnc2()); // lib
console.log(obj.fnc3()); // lib


うーん。parent をキーワードっぽく使いたいだけなのに、危険なコードな上に関数ごとに eval はきっついなぁ。微妙だ。 JSON.stringify とか関数そのまま維持してくれたらラクなのに(オイッ)。

ま、こういうの、ホント面白いね。私だけかもしんないが。
今回は(も)お遊びです。循環参照には注意が必要です。unload 時に全て解除するようなことも可能ですが。



posted by HiFa at 14:01 | 愛知 ☀ | Comment(0) | TrackBack(0) | JavaScript雑感 | このブログの読者になる | 更新情報をチェックする
>>> スパムコメントは消してますよん。 お互い無駄な労力は避けましょう。 <<<

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック