※ ローカル変数云々というより、関数を 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 時に全て解除するようなことも可能ですが。
この記事へのコメント