9

I'd like to call functions I've defined within the document ready function of jQuery, but am having a bit of trouble. I have the following code:

jQuery(document).ready( function($) {

    function test1() {
        alert('test1');
    }

    function test2() {
        alert('test2');
    }

    var test_call = '2';

    var fn = 'test' + test_call;

    // use fn to call test2

});

I don't want to use eval, and window[fn] doesn't seem to be working. The two test functions don't appear to be indices in the window variable. I appreciate the help and knowledge.

Evan
  • 1,316
  • 2
  • 14
  • 19

2 Answers2

12

All I can think of that doesn't use eval() or some form of eval (passing a string to setTimeout() is a form of eval()), is to register the relevant function names on an object and then look up the function name on that object:

jQuery(document).ready( function($) {

    function test1() {
        alert('test1');
    }

    function test2() {
        alert('test2');
    }

    // register functions on an object
    var funcList = {};
    funcList["test1"] = test1;
    funcList["test2"] = test2;


    var test_call = '2';

    var fn = 'test' + test_call;

    if (fn in funcList) {
        funcList[fn]();
    }

});

or the registration could be done in the definition of the functions. If they were global functions, they would be implicitly registered on the window object, but these are not global as they are scoped inside the document.ready handler function:

jQuery(document).ready( function($) {

    var funcList = {};

    funcList.test1 = function test1() {
        alert('test1');
    }

    funcList.test2 = function test2() {
        alert('test2');
    }

    var test_call = '2';
    var fn = 'test' + test_call;

    if (fn in funcList) {
        funcList[fn]();
    }

});

Or, you could move the functions to the global scope so they are automatically registered with the window object like this:

function test1() {
    alert('test1');
}

function test2() {
    alert('test2');
}

jQuery(document).ready( function($) {

    var test_call = '2';
    var fn = 'test' + test_call;

    if (fn in window) {
        window[fn]();
    }

});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks jfriend00, this is the route I'll be taking. I wasn't sure if there was a different global variable (or something similar with jQuery) I was missing which handled the functions scoped in the document.ready. – Evan Sep 15 '11 at 14:44
  • The code inside document.ready is just code in an anonymous function, thus there is no named scope that can be addressed there. The functions declared in there are just local functions (same as local variables). You could move the function definitions to the global scope so they'd automatically be registered with the window object (see the last option I just added to my answer). – jfriend00 Sep 15 '11 at 15:19
3

The best way, if not Eval, would be to use setTimeout with zero milliseconds, as you can specify the function as a string.

setTimeout('myfunction()',0,);
andy
  • 8,775
  • 13
  • 77
  • 122
  • Even though there is no explicit call to `eval()`, this is still using `eval()` interally and is subject to any issues one might be concerned about with eval (like executing arbitrary code from an outside source). This also doesn't happen synchronously before the next line of code if that's important. – jfriend00 Sep 15 '11 at 00:57