views:

147

answers:

4

Hi everyone,

I'd like to fire a function. Unfortunately I can't call it directly as the functions' name is provided as a string.

Example:

function myFunction() {
   alert('I am myFunction');
}
function anotherFunction() {
   alert('I am anotherFunction');
}

var func_name = 'myFunction';

$obj = jQuery('a');

$obj.each(function(){
   $(this).func_name(); // eval didn't help here :( 
});

Obviously this doesn't work, as JS expects func_name to be a valid function. Is there a way to have myFunction() fired instead of func_name()? Thanks.

UPDATE: Well, after testing some of the answers, it seems that my problem description isn't complete. :O I updated the code to include an object, which I want the function to be attached/run on.

Thanks again!

A: 
eval(func_name + "()");

Eval will take a string and evaluate it at runtime.

David Andres
Explanations needed for point deductions. This is a valid approach regardless of your personal opinions.
David Andres
+5  A: 

No reason to use eval. If your function is global, use window[func_name]()

With your updated question:

//the function $ returns an object, thus, this is changed
$(this).func_name();

//to this:
$(this)[func_name]();
Jani Hartikainen
Indeed. But I'll leave my answer, anyway. Just for the case it's not global ;-)
Michael Krelin - hacker
Good answer. In JavaScript, most things you can do with a dot operator, you can also do with bracket notation. so a.foo() and a['foo']() do the same thing. Stay away from eval() whenever you can.
Nosredna
so, just to make sure I get this right. the 'a' is an object? and 'foo' is the functions name here? Then my current jQuery(this).eval(function_name+'()'); becomes jQuery(this)[function_name](); right?
Updated answer.
Jani Hartikainen
actually I don't get it to work. Seems I'm missing something... but what?Greatly appreciated if someone might take a look at http://contactsheet.de/sandbox/autoload/index.html in comparison tohttp://contactsheet.de/sandbox/autoload/index2.html (where I'm trying to fire the same plugin with the discussed method - right after the alert). Thank you so much!
As far as I can tell the problem seems to be that you're not giving the function correct arguments. Otherwise it looks correct.
Jani Hartikainen
+2  A: 

For methods, use

obj[func_name]()

Remember that globally declared functions are properties of the global object (ie window in browsers).

For local functions, as far as I know there's no way around

eval(func_name)()
Christoph
For local, try this[func_name]();
Nosredna
`this` is not quite local, what he meant is `(function(){ function A(){}; eval('A')(); })();`
Michael Krelin - hacker
+2  A: 

As other have mentioned, this is done with property accessor operators - "[" and "]". What matters in this case is how this function is declared and where it's being referenced from.

If it is declared globally (i.e. in the global scope, as function declaration or function expression), or assigned to a property of a Global Object at some point, then it is possible to access it as a property of a Global Object. In 3rd. edition of ECMAScript-262, one can access Global Object with an expression such as:

(function(){ return this; })();
// or just `this` when in global scope

(Note that in browsers, Global Object is usually the same object as the one referenced by global window, although it doesn't have to be that way).

So you would access global function as:

var globalObj = (function(){ return this; })();
globalObj['your_func'];

// or via `window`
window['your_func'];

The problem usually arises when function is declared locally – that is in another function body:

(function(){
  function your_func(){};
  // how to access `your_func` here?
});

The problem is essentially due to the fact that while it is possible to access Global Object (as in previous example), it's not possible to access function's Variable Object (i.e. object used as a "base" for variable and function declaration in function code).

You can certainly use eval in cases like that but it's most definitely a wrong approach to the problem. A much easier, more compatible and runtime-efficient way is to attach function as a property of some local object:

(function(){
  ...
  function your_func(){}
  var funcs = { your_func: your_func };
  ...
})();

then use the very same brackets to access a property – property referencing function in question:

funcs['your_func'];
kangax