編集: Bergiは私の最初の答えが間違っていると指摘しました。彼は正しいです。eval
独自のスコープで実行され、関数コンストラクターは仕様に従って関数スコープで実行されるため、これはどちらでも不可能です。
vm
コードの実行場所をより細かく制御できるモジュールを使用して node.js でこの種のことを自分で何度か行ったことがありますが、ブラウザには別のアプローチが必要なようです。
このような方法で変数を共有できる唯一の方法は、JavaScript 実行のグローバル スコープ (おそらく iframe) で共有することです。これを行う 1 つの方法は、スクリプト タグ インジェクションです。
function run(code){
var sc = document.createElement("script");
sc.setAttribute("type","text/javascript");
sc.innerHTML = code;
document.body.appendChild(sc);
}
run("var x = 5");
run("document.write(x)");
(これがこのコードの動作です)
スコープ ラッパーに関しては、それらを同じフレームに挿入する代わりに、別のフレームに挿入しますiframe
。これにより、window オブジェクトの範囲がその iframe に限定され、コンテキストを共有できるようになります。
以前の回答をお詫び申し上げます。仕様を読み間違えました。この回答がお役に立てば幸いです。
eval
以前の回答をここに残しておきます。これは、Function
コンストラクターがどのように機能するかについての洞察を提供するとまだ信じているからです。
非厳密モードでコードを実行するeval
と、ページの現在のコンテキストで実行されます。関数の宣言が完了すると、それが宣言されたスコープが終了し、それとともに関数が終了します。
Function コンストラクターの使用を検討してから、それを.call
ing します。
あなたの場合、それは次のようになります:
var scopeWrapper = {};
scopeWrapper.run = function(code){
var functionToRun = new Function(code);
functionToRun.call(scopeWrapper);
}
scopeWrapper.run('this.test = function() { alert("passed"); }');
scopeWrapper.run("this.test()")
仕様からの直接の参照は次のとおりです。
呼び出しコンテキストがない場合、または eval 関数への直接呼び出し (15.1.2.1.1) によって eval コードが評価されていない場合は、eval コードを C として使用して、グローバル実行コンテキストであるかのように実行コンテキストを初期化します。 10.4.1.1 で説明されているとおり。
このコードが node.js で実行される場合は、vmモジュールの使用を検討してください。また、このアプローチは、実行するコードがコードを変更できるという点でまだ安全ではないことに注意してください。