2

So you want to execute a function whose name is in a string or variable:

var fn = "foobar";

function foobar() {
    console.log('say something');
}

Answers like this - How to execute a JavaScript function when I have its name as a string - say to do this:

window[fn](); // outputs 'say something'

But... this does not work for some reason:

jQuery(document).ready(function($){
    var fn = "foobar";

    function foobar() {
        console.log('say something');
    }

    window[fn](); // undefined
});

This works, however:

jQuery(document).ready(function($){
    var fn = "foobar";

    window[fn](); // outputs 'say something'
});

/* I'm outside the ready handler */

function foobar() {
    console.log('say something');
}

I want to keep my functions inside that ready handler so I don't have to write a bunch of anonymous functions to define jQuery as $. How do I do that?


Update

Here's what I'm wanting to do:

<div data-control="toggleNext">FAQ</div>
<div>Here's some text that will be hidden until toggled</div>

JS:

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

    function toggleNext() {
        // add ".js_toggled" to .next() element
    }

    $('[data-control]').each(function(){
        var fn = window[$(this).data('control')]; // <-- this don't werk
        if (typeof fn === 'function') fn(this);
    });

});
Community
  • 1
  • 1
Phil Tune
  • 3,154
  • 3
  • 24
  • 46
  • 1
    If your function is inside the ready handler, it won't be available on window unless you specifically set it as such. but, that's a bad idea anyway, just leave `window` out of it and define your own object local to your doc ready block. – Kevin B Sep 22 '15 at 20:23
  • Oh, you mean like `window[foobar] = function() {}` ? – Phil Tune Sep 22 '15 at 20:24

2 Answers2

2

If your function is inside the ready handler, it won't be available on window unless you specifically set it as such. However, that's a bad idea anyway, just leave window out of it and define your own object local to your doc ready block.

jQuery(document).ready(function($){
    var fn = "foobar", methods = {};
    methods[fn] = function () {
        console.log('say something');
    }
    $('[data-control]').each(function(){
        var fn = methods[$(this).data('control')];
        if (typeof fn === 'function') fn(this);
    });
    //methods[fn](); 
});
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Hmm, well I wanted to do something like `
    ` and loop through various `[data-control]`'s and translate them into functions... So doing `methods[fn]` seems one-time use.
    – Phil Tune Sep 22 '15 at 20:30
  • Can you show an example? seems like that wouldn't be limited to using `window` – Kevin B Sep 22 '15 at 20:31
  • I thought I'd write out my solution as well. Thanks for the help. This was one of those hard-to-research-what-you-don't-know questions. – Phil Tune Sep 22 '15 at 20:52
2

@KevinB led me to the answer and I'll give him the accept, but I thought this was worth writing out since I imagine other folks out there would want to do something like this.

Since the window object does not include functions declared inside the ready handler (that is, without explicitly calling window['functionName'] = function() {...}), you can define a local object and call it instead:

HTML:

<div data-control="toggleNext">FAQ</div>
<div>Here's some text that will be hidden until toggled</div>

JS:

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

    var myFuncs = {

        toggleNext : function(me) {
            // add ".js_toggled" to $(me).next() element
        },

        doSomethingCool : function() {
            // you'd better make it good
        }
    }

    $('[data-control]').each(function(){

        var funcName = $(this).data('control'),
            fn = myFuncs[funcName];
        if (typeof fn === 'function')
            fn(this);

    });

});

I dunno, am I the only one that finds this useful?

Phil Tune
  • 3,154
  • 3
  • 24
  • 46