3

相互に依存するスクリプト ブロックがいくつかあります。それらを 1 つのスコープで実行する必要があります。

私の試み:

var scopeWrapper = {}; 

with(scopeWrapper) {
    (function() {
        this.run = function(code) {
            eval(code);
        };
    }).call(scopeWrapper);
}

scopeWrapper.run('function test() { alert("passed"); }');
scopeWrapper.run('test();');

「テストが定義されていません」というエラーが表示されます。コードは異なるスコープで実行されているようです。なぜこうなった?

4

2 に答える 2

8

編集: 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 コンストラクターの使用を検討してから、それを.calling します。

あなたの場合、それは次のようになります:

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モジュールの使用を検討してください。また、このアプローチは、実行するコードがコードを変更できるという点でまだ安全ではないことに注意してください。

于 2013-03-14T12:47:34.763 に答える
0

testのスコープ内にのみ存在し、this.run呼び出し時にのみ存在します:

// global scope
(function(){
  // local scope (equivalent of your "run" function scope)
  eval('function f(){};');
  console.log(f); // prints "function f(){}"
})();
console.log(f); // prints "ReferenceError: f is not defined"

を呼び出すたびに、それぞれが個別に評価されるrun新しいスコープが作成されます。code

于 2013-03-14T12:54:37.713 に答える