2012-04-03 11 views
4

動的にjavascript関数のスコープを拡張することはできますか?私は成功せず、次を試してみました:javascript関数のスコープを拡張する

function foo() 
{ 
    var bar = 12; 
    return function(x) 
    { 
     return eval(x); 
    } 
} 

var e = foo(); 

console.log(e("bar"));   // 12 
console.log(e("bar = 42;"));  // 42 
console.log(e("bar"));   // 42 
console.log(e("var baz = 99;")); // undefined 
console.log(e("baz"));   // ReferenceError: baz is not defined 

私はラインbaz = 99からvarを削除しかし、その後バズ変数は(これは私には完璧な意味があります)グローバルになった場合:

... 
console.log(e("baz = 99;"));  // 99 
console.log(e("baz"));   // 99 
console.log(baz);    // 99 (so baz is just a global) 
+2

あなたはこれをしたいと思うなぜ、これは地獄のよう – Raynos

+0

@Raynos汚れている:ふふふ...かもしれないが、私はそれは恐ろしいだとは思わない:私は楽しみのためにJavascriptをターゲットコンパイラを書くとしていますモジュールを実装したいのですが、関数スコープを使用することが可能かどうかは、モジュールを「オープン」にしておくことです(つまり、すべての名前を一度に定義してモジュールを封印する代わりに、 "その後) – 6502

+0

代わりにオブジェクトを使うことを考えましたか?モジュールのコンテナとして関数スコープを使用することはできません – Raynos

答えて

1

毎回、それはその関数呼び出しのスタック上の変数を作成していますので、あなたがそれを呼び出す次回利用できるようにするつもりはありません。

変数をスコープに動的に追加する必要がある場合は、私はRaynoの提案を使用し、マップを使用します。 http://jsfiddle.net/UVSrD/

function foo() 
{ 
    var scope = {}; 
    return function(x) 
    { 
     return eval(x); 
    } 
} 


var e = foo(); 

console.log(e("scope.bar = 12")); // 12 
console.log(e("scope.bar")); // 12 
console.log(e("scope.baz = 14")); // 14 
console.log(e("scope.baz;")); // 14 
// Not a global 
console.log(typeof scope) // undefined 
+0

'var baz = 99;の評価がうまくいかなかった理由を理解しました...問題は、アクセスしたい範囲が' foo'によって返された関数ではなく、外側のものです。ローカルオブジェクトを使用することはオプションですが、すべてのアクセスに対してダブルルックアップを使用することを意味します(最初に 'scope'を探し、変数または関数を検索します)。 – 6502

+0

はい、スコープチェーンはレキシカルなので、変更することはできません。 –

+0

あなたの最後のコメントが私にとって理にかなっているので、私は受け入れました。あまりにも悪いのは、あらかじめ定義されているレキシカル変数が囲みスコープにバインドされていないということです。固定サイズのレキシカルスコープを使用すると、実装が簡単になり、ある程度の最適化が可能になるため、意図的です。 example evalは、実装が閉じられたover変数だけでなく、クロージャのスコープ全体で閉じるように強制されているすべてのレキシカルにアクセスできる必要があります。 – 6502

0

あなたが作成しています

function foo() 
{ 
    var bar = 12; 
    return function(x) 
    { 
     return eval(x); 
    } 
} 

すでにバーコードに設定されているオーバーライドバーを12に渡すと、私は何がわかりません達成しようとしていますが、クロージャを使用すると外部関数の変数が保持されます。

+0

はい私はクロージャを作成していますが、2番目の 'eval'はキャプチャされた変数を変更しています。問題は、「取り込み変数」とローカル関数を後で追加するかどうかということです。 – 6502

0

Evalは、呼び出される場所のどこでも実行されます。表示される動作は、次の行にあるためです。

console.log(e("var baz = 99;")); // undefined 

返される関数のローカルスコープにvar baz = 99を作成します。 var name = valueの戻り値。あなたは未定義です。後で電話するとき

console.log(e("baz"));   // ReferenceError: baz is not defined 

あなたはbazが定義されていない新しい関数を返します。

これはちょっとクールです:あなたはe("var baz = 4")を呼び出すhttp://www.bennadel.com/blog/1926-Exploring-Javascript-s-eval-Capabilities-And-Closure-Scoping.htm

+0

実際にその実験を行うとき、私は後で 'var baz 'の評価がうまくいかないことを理解しました。私の質問は、1つのレベルをエスケープして包含スコープに到達できるかどうかです。 – 6502

+0

私はこれが可能であると考えています。なぜなら、2つのレベルの範囲を変更する必要があるからです。私が知る限り、範囲に直接影響する方法はありません。新しいオブジェクトを作成して返すこともできますが、作成されたスコープを直接変更することはできません。 –

関連する問題