在类中执行私有函数的名称(字符串)

时间:2013-05-08 23:53:57

标签: javascript class function callback

目前我有这样简单的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();!这只是一个随机值。

2 个答案:

答案 0 :(得分:5)

参考更新:

而不是设置:

 var funcName = "getRandomEffectFunctionNeme()";

因此,设置对函数的名称的引用应该

 var funcRef = getRandomEffectFunctionNeme;

并设置对函数本身的引用。这不仅避免了setTimeout字符串有*的问题。它还解决了你的闭包问题,因为你的代码的构造方式是超时可以访问函数本身。

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

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

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时,无论如何它都可以访问它,因为它们在同一个闭包中。

答案 1 :(得分:2)

注意:此解决方案为only applicable if you can not pass the function name as a function reference,例如,如果您正在使用不受控制的代码进行集成。通常,在可能的情况下,您应该传递一个函数引用,因为在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与字符串一起使用可能会出现问题,因此很难进行调试或维护。