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();

我在按其名称执行此功能时遇到了一些麻烦。如果我只是eval(funcName);而不是 setTimeout 调用它可以正常工作,但无法弄清楚为什么它不能以这种方式工作。

当然,这是更复杂代码的一部分,但其余代码与此问题无关。

我的问题很明显 - 如何通过将函数的名称设置为setTimeout函数的参数来执行函数?可能吗?

注意:将此功能设为公开 ( this.myTestFunc = ...) 不是一种选择!

更新:

funcName = "myTestFunc()";只是一个例子。在实际代码中它看起来像funcName = getRandomEffectFunctionName();!这只是一个随机值。

4

2 回答 2

5

参考更新:

而不是设置:

 var funcName = "getRandomEffectFunctionNeme()";

因此,设置对函数名称的引用,您应该这样做

 var funcRef = getRandomEffectFunctionNeme;

并设置对函数本身的引用。这不仅避免了setTimeout 字符串 has* 的问题。它还解决了您的关闭问题,因为您的代码的结构使得超时可以访问函数本身。

在您的情况下,假设您有一些过滤器功能,例如lowPass highPassblur。在这种情况下,我们将选择一个函数,而不是选择一个函数名。

首先,我们将这些函数存储在一个数组中:

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调用在全局上下文中执行,因为它在计时器中。这意味着它们不再处于相同的词法范围内。

但是,您可以通过巧妙地使用来获取对该函数的引用eval,稍后您可以在调用中setTimeout调用它。

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 回答