javascript equivalent of PHP's call_user_func()

10,294

Solution 1

If a function is defined at the global level, then it automatically becomes a child of the window object.

Therefore you can always call window.functionName(); any place you would normally just call functionName();.

Further, since in Javascript objects work like associative arrays, you can call any child of any object using array syntax like this: object['childName']. This includes functions, so you can do object['functionName'](); for any function which is a member of an object.

Combining these two points together, you can call any globally defined function like so:

window['functionName']();

And since functionName in the above example is a string, you can use a variable in those brackets, which means you've got the same functionality as PHP's call_user_func().

[EDIT]

As I stated, this works for any object. The OP's comments state that the functions he wants to use this way are in a JQuery plug-in. They are therefore likely to be part of the JQuery object, and would normally be called like so: JQuery().functionName(); (or with the $ in place of JQuery).

Javascript syntax allows us to use ['functionName']() in any place where we can use .functionName(), so therefore, taking the above JQuery example, we could change it to look like this:

JQuery()['functionName']();`

But this technique can be adapted for any Javascript object. Any place where you use .functionName(), it can be replaced with ['functionName']().

Solution 2

There are quite a few ways of achieving this. The quickest and the dirties (and unsafe!) way is to do (PS:fnName in the below examples is the name of the function stored as string)

eval(fnName)

However you can also do

            this[fnName]();//careful with "this" though. Try replacing with "window" if it doesnt work for you

or to call it by passing arguments

this[fnName].apply(contextObject,argumentArray) //contextObject will be objest which will be referenced by the keyword "this" within the function body (fnName's body), argumentArrayy is the array of arguments you want to pass to function.

Solution 3

var a = function(foo) {console.log(foo);}

a.call(null, 'test');
a('test');
Share:
10,294
Alex
Author by

Alex

I'm still learning so I'm only here to ask questions :P

Updated on July 24, 2022

Comments

  • Alex
    Alex almost 2 years

    Does anyone know if there is one?

    I want to call a function using a variable name.


    edit:

    I posted a fiddle here with what I'm trying to do:

    http://jsfiddle.net/sAzPA/

    <div id="some">
      ...
    </div>
    

    js:

    (function($){
      $.fn.MyPlugin = function(){
    
        return this.each(function(){
           var somefunction = function(arg1, arg2){ alert(arg1); },
               someotherfunction = function(arg1, arg2){ alert(arg2); },
               reallyimportantfunction = function(arg1, arg2){
                var foo = $(this).attr('id') + 'function';
    
                // here I want to call the function with the foo value as name, and pass it arg1 and arg2
    
                $()[foo](arg1, arg2); // <- doesn't work
    
               };
    
           reallyimportantfunction();
        });
      };  
    })(jQuery);
    
    
    jQuery(function($){
      $('#some').MyPlugin ();
    
    });
    
  • gnud
    gnud about 13 years
    Ehm, browser javascript is inherently unsafe. The client can alter the code at will. I would be a lot more scared of using the php eval(). Just make sure you check rigorously any data you submit, server-side.
  • Nikhil
    Nikhil about 13 years
    that is quite true. However eval is much misunderstood. Most programmers immediately yell "EVIL!!!" as soon as they see eval whereas there are genuine cases where eval is very helpful and is recommended!
  • Spudley
    Spudley about 13 years
    genuine cases yes, but they're few and far between.
  • Alex
    Alex about 13 years
    the function (actually a set of functions) is a function variable inside a jquery plugin. I'm trying to call this function with parameters from a different function variable from the same plugin
  • Spudley
    Spudley about 13 years
    @Alex: in that case, the functions you want are children of the JQuery object, so as per my answer above, you should be able to do JQuery['functionName']();
  • Spudley
    Spudley about 13 years
    @Alex: hmm. Actually, more likely JQuery()['functionName'](). But how would you normally call the function, ie if you were calling it normally? Any time you can use .functionName(), you can replace it with ['functionName'](), so look at your current usage of the function, and adapt this technique to suit.
  • Alex
    Alex about 13 years
    if I would call it normally it would be somefunction('bla', 'bla'); :)
  • Spudley
    Spudley about 13 years
    well in that case, the original window['functionName']() example should work -- as so: window['somefunction']('bla', 'bla');
  • Spudley
    Spudley about 13 years
    Okay. In the example you've given, the function is declared within the scope of another function. It is therefore local scope, and not global scope. This means that the window[] option won't work, because it's not part of the window object. But the real problem you've got there is that $(this).attr('id')+'function'; returns undefinedfunction because this is not the same object that you're expecting inside the closure. I've modified your fiddle so that $(this) works inside the closure and the functions have scope as well. It now works as you want it to: jsfiddle.net/RRvz2/1
  • Warbo
    Warbo over 9 years
    The browser's user is not the enemy; malicious users trying to do them harm are. We can prevent XSS by escaping user-provided data, but 'eval' can make that data harmful again! The more we use 'eval', the more chance a malicious user will find a way to get their data passed to it and hence bypass our XSS prevention. Also, "eval" can hinder code analysis, eg. asking an IDE to find all uses of a function.
  • Warbo
    Warbo over 9 years
    This seems to be encouraging globals :(
  • Average Joe
    Average Joe over 6 years
    Spudley, Your JQuery example includes a trailing char which you do not want in there. Correct version should be JQuery()['functionName']();