[英]Execute private function inside the class by its name (string)
At the moment I have simple JavaScript class like this: 目前,我有一个简单的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 ...
}
and to test it I'm using this code: 并对其进行测试,我使用以下代码:
x = new MyClass();
x.Create();
I have some troubles to execute this function by it's name. 我很难按其名称执行此功能。 If I put just
eval(funcName);
如果我只把
eval(funcName);
instead of setTimeout call it works fine but can't figure out why it doesn't work this way. 而不是setTimeout调用,它可以正常工作,但无法弄清楚为什么它不能以这种方式工作。
Course, this is part of more complex code but rest of code is irrelevant to this problem. 当然,这是更复杂的代码的一部分,但其余代码与该问题无关。
My question is obvious - How to execute function by its name set as setTimeout
function's argument? 我的问题很明显-如何通过将名称设置为
setTimeout
函数的参数来执行函数? Is it possible? 可能吗?
Note: Making this function public ( this.myTestFunc = ...
) isn't an option! 注意:不能公开此函数(
this.myTestFunc = ...
)!
funcName = "myTestFunc()";
is just an example. 只是一个例子。 In real code it looks like
funcName = getRandomEffectFunctionName();
在实际代码中,它看起来像
funcName = getRandomEffectFunctionName();
! ! It's just a random value.
这只是一个随机值。
Referring to the update: 参考更新:
Instead of setting: 而不是设置:
var funcName = "getRandomEffectFunctionNeme()";
Thus, setting a reference to the function's name you should do 因此,设置对函数名称的引用应该
var funcRef = getRandomEffectFunctionNeme;
And set a reference to the function itself . 并设置对函数本身的引用。 Not only this avoids the issues
setTimeout
with strings has*. 这不仅避免了带有字符串has *的
setTimeout
问题。 It also solves your closure issue since your code is structured in such a way the timeout has access to the function itself. 由于代码的结构以超时可以访问函数本身的方式构造,因此它也解决了关闭问题。
In your case, let's assume you have some functions that are filters, for example lowPass
highPass
and blur
. 在您的情况下,我们假设您具有一些过滤器功能,例如
lowPass
highPass
和blur
。 In that case, instead of choosing a function name we would be choosing a function. 在这种情况下,我们将选择功能而不是选择功能名称 。
First, we store these functions in an array: 首先,我们将这些函数存储在数组中:
var filters = [lowPass,highPass,blur];
In JavaScript, functions are first-class objects, you can pass them around just like other objects. 在JavaScript中,函数是一流的对象,您可以像其他对象一样传递它们。
Next, we'll get a random number 接下来,我们将获得一个随机数
var chosen = Math.floor(Math.random()*3);//get a random number between 0 and 2
Finally, we'll choose the filter and invoke it 最后,我们将选择过滤器并调用它
var filter = filters[chosen];
setTimeout(filter,1000);
( * just try debugging it, it basically invokes the compiler whenever ran and is painfully slow) (*只是尝试调试它,它基本上在运行时会调用编译器 ,并且运行缓慢)
You just pass a function to setTimeout as a parameter, rather then a string, setTimeout(myTestFunc,1000)
. 您只需将一个函数传递给setTimeout作为参数,而不是字符串
setTimeout(myTestFunc,1000)
。
When calling Create
it would have access to it anyway because they are in the same closure. 调用
Create
时,无论如何都可以访问它,因为它们处于同一闭包中。
NOTE: This solution is only applicable if you can not pass the function name as a function reference , for example if you're integrating with code that is outside your control. 注意:此解决方案仅在您不能将函数名称作为函数引用传递时才适用 ,例如,如果您正在与控件之外的代码集成。 Generally, when possible, you should pass a function reference since in JavaScript, all functions are objects.
通常,在可能的情况下,您应该传递函数引用,因为在JavaScript中,所有函数都是对象。
Assuming that the timeout and the function are in the same closure your code is pretty close. 假设超时和函数在同一个闭包中,则代码非常接近。 The problem is that your eval call executes in the global context because it is in a timer.
问题在于您的eval调用在全局上下文中执行,因为它在计时器中。 This means they are no longer in the same lexical scope.
这意味着它们不再处于相同的词汇范围内。
You can however, grab a reference to the function by clever use of eval
which you can later call in the setTimeout
invocation. 但是,您可以通过巧妙地使用
eval
来获取对该函数的引用 ,您可以稍后在setTimeout
调用中对其进行调用。
var F=eval(funcName);// gain a reference to the function given the function's name
cTimer = setTimeout(F, 1000);
If you're using AIR or don't trust the functionName string you can do the following: 如果您使用的是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");
This is preferable since you are invoking setTimeout
with a function's name and not a string. 这是可取的,因为您要使用函数名称而不是字符串来调用
setTimeout
。 In general, using setTimeout
with a string can have issues, it's hard to debug or maintain. 通常,将
setTimeout
与字符串一起使用可能会遇到问题,很难调试或维护。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.