目前我有这样简单的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();
!这只是一个随机值。
答案 0 :(得分:5)
参考更新:
而不是设置:
var funcName = "getRandomEffectFunctionNeme()";
因此,设置对函数的名称的引用应该
var funcRef = getRandomEffectFunctionNeme;
并设置对函数本身的引用。这不仅避免了setTimeout
字符串有*的问题。它还解决了你的闭包问题,因为你的代码的构造方式是超时可以访问函数本身。
在您的情况下,我们假设您有一些过滤器功能,例如lowPass
highPass
和blur
。在这种情况下,我们将选择一个函数,而不是选择函数 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
与字符串一起使用可能会出现问题,因此很难进行调试或维护。