3

Yeah, there are numerous questions like How to turn a String into a javascript function call? or How to execute a JavaScript function when I have its name as a string.

But what if we have not a plain function name, but an object property name which in fact is a function?

Like:

var callMe = 'foo.bar.baz';

and the code expected to be called is:

window.foo = {
    bar: {
        baz: function() {
            alert('Eureka!');
        }
    }
};

Why I need this: the callback parameter is passed via url and it can (by application design) be either a function name or FQN of object's property.

Any ideas others than eval()?

UPD:

My final implementation:

var parts = callbackName.split('.'),
    callback;

for (i in parts) {
    if (!callback) {
        callback = window[parts[i]];
    } else {
        callback = callback[parts[i]];
    }

    if (typeof callback === 'undefined') break;
}

if (typeof callback === 'function') {
    callback();
} else {
    console.error('Passed callback is not a valid function');
}
0

4 Answers 4

5

try

window['foo']['bar']['baz']()

If this works for you, should be easy to translate 'foo.bar.baz' into that.

Sign up to request clarification or add additional context in comments.

2 Comments

Yep it does... It was so obvious :-S
You can always relate to a Sherlock Holmes story, where the Scotland Yard where looking in a house for a letter and couldn't find it. They brought Holmes, who walked to the desk in the study and picked an envelop that was lying on top of it. that was the letter...
1

See the code below and check out the fiddle ( http://jsfiddle.net/bxsHp/ ) :

window.foo = {
    bar: {
        baz: function() {
            alert('Eureka!');
        }
    }
};
//foo.bar.baz();
var callme = "foo.bar.baz";
var fn = window[callme.split(".")[0]];//get the first prop. bar
var len = callme.split(".").length;//length of obj tree
for(i=1;i < len;i++)
{//search for the next obj  
  fn = fn[callme.split(".")[i]];
}
if(typeof(fn) == "function")
{//check and call
  fn();
}

Comments

1

You could always make use of reduce().

callMe.split('.').reduce(function(prev, value) {
    return prev[value] || function() {};
}, window)();

jsFiddle.

The || function() {} is to prevent an error if the object/function list is undefined somewhere. If you are using jQuery, you could swap the empty function literal with $.noop().

Of course, supporting older IEs will mean you need to shim Array.prototype.reduce().

Comments

0

This is probably not the most elegant way of doing this, but it should work:

var callMe = "foo.bar.baz".split('.');

var callMeParts = callMe.split('.');

var fnCallMe = null;
var obj = window;
for (var i = 0; i < callMeParts.length; i++) {
    var prop = callMeParts[i];
    if (typeof obj[prop] === 'undefined') break;

    if ((i + 1) === callMeParts.length && typeof obj[prop] === 'function') {
        fnCallMe = obj[prop];
        break;
    }
    obj = obj[prop];
}

if (fnCallMe !== null) {
    fnCallMe.call(obj); // Call the function using the function container as the "scope"
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.