0

現時点では、次のような単純な JavaScript クラスがあります。

function MyClass() {

// ... some code ...

this.Create = function() {
  funcName = 'myTestFunc()';
  cTimer = setTimeout(funcName, 1000);
  }

// ... more code ...

var myTestFunc = function() {
  alert ('everything\'s OK!');
  }

// ... more code ...
}

それをテストするために、私はこのコードを使用しています:

x = new MyClass();
x.Create();

この関数を名前で実行するのに問題があります。setTimeout 呼び出しの代わりに置くと正常にeval(funcName);動作しますが、なぜこのように動作しないのかわかりません。

もちろん、これはより複雑なコードの一部ですが、残りのコードはこの問題とは無関係です。

setTimeout私の質問は明らかです-関数の引数として設定された名前で関数を実行する方法は? 出来ますか?

注: この関数を公開する ( this.myTestFunc = ...) ことはできません。

アップデート:

funcName = "myTestFunc()";はほんの一例です。実際のコードでは、次のようになりfuncName = getRandomEffectFunctionName();ます。ただのランダム値です。

4

2 に答える 2

5

アップデートを参照してください:

設定する代わりに:

 var funcName = "getRandomEffectFunctionNeme()";

したがって、関数の名前への参照を設定する必要があります

 var funcRef = getRandomEffectFunctionNeme;

そして、関数自体への参照を設定します。setTimeout これにより、文字列 has*の問題が回避されるだけではありません。また、タイムアウトが関数自体にアクセスできるようにコードが構造化されているため、クロージャーの問題も解決します。

lowPass highPassあなたの場合、フィルタであるいくつかの関数があると仮定しましょうblur。その場合、関数を選択する代わりに、関数を選択します。

まず、これらの関数を配列に格納します。

var filters = [lowPass,highPass,blur];

JavaScript では、関数は第一級のオブジェクトであり、他のオブジェクトと同じように渡すことができます。

次に、乱数を取得します

var chosen = Math.floor(Math.random()*3);//get a random number between 0 and 2

最後に、フィルタを選択して呼び出します

var filter = filters[chosen];
setTimeout(filter,1000);

( * デバッグしてみてください。基本的に、実行するたびにコンパイラが呼び出され、非常に遅いです)


文字列ではなく、パラメータとして setTimeout に関数を渡すだけですsetTimeout(myTestFunc,1000)

Createそれらは同じクロージャーにあるため、呼び出すととにかくアクセスできます。

于 2013-05-08T23:56:18.603 に答える
2

注:この解決策は、関数名を関数参照として渡すことができない場合にのみ適用できます。たとえば、制御できないコードと統合している場合などです。一般に、JavaScript ではすべての関数がオブジェクトであるため、可能であれば関数参照を渡す必要があります。

タイムアウトと関数が同じクロージャーにあると仮定すると、コードはかなり近いものになります。問題は、eval呼び出しがタイマー内にあるため、グローバル コンテキストで実行されることです。これは、それらが同じレキシカル スコープ内にないことを意味します。

ただし、後で呼び出しで呼び出すことができる巧妙な使用により、関数への参照を取得できます。evalsetTimeout

var F=eval(funcName);// gain a reference to the function given the function's name
cTimer = setTimeout(F, 1000);

AIR を使用している場合、または functionName 文字列を信頼しない場合は、次の操作を実行できます。

function Test(){
 var functionContainer={
  t:function(){
   console.log("it's t");
  }
 };
 this.callT=function(functionName){
  var F=functionContainer[functionName];
  console.log("F is:",F);
  setTimeout(F,500);
 }
}
(new Test()).call("t");

setTimeout文字列ではなく関数の名前で呼び出すため、これは望ましい方法です。一般にsetTimeout、文字列を使用すると問題が発生する可能性があり、デバッグや保守が困難になります。

于 2013-05-08T23:56:59.340 に答える