Tuesday, May 3, 2011

How to get a reference to a JavaScript function object from its name as a string?

In JavaScript, if I have a string in a variable, is there a way to get a reference to the function object which has that matching name? Note that jQuery is available to me so I can use any of its helper methods also.

For example:

myFunction = function(){};

var func_name = "myFunction";
var myFunctionPtr = ???  //how to get the function from the name

Thanks

From stackoverflow
  • if you know that its a global function you can use:

    var functPtr = window[func_name];
    //functPtr()
    

    Otherwise replace window with the parent object containing the function.

  • this[func_name] should give you the function.

    var myfunc = this[func_name];
    myfunc();
    
    rmeador : I just tried that in Firebug and it didn't work. Maybe it behaves differently in a web page?
    Max Schmeling : It depends on where your function is defined. If the function is not defined on 'this' then it won't find it. You may need to try window[func_name] or Some.Other.Object[func_name]
  • Use eval:

    myFunction = function(){};
    
    var func_name = "myFunction";
    var myFunctionPtr = eval(func_name);
    
    mkoryak : eval is evil. dont use eval
    Jon Benedicto : why? can you cite some good reasons.
    Miles : http://stackoverflow.com/questions/86513/why-is-using-javascript-eval-function-a-bad-idea
    Jon Benedicto : thanks for the link. as with all programming languages, libraries and methods, it can be abused. The key is using it correctly, and knowing what one is doing. If those conditions are met, it's the right tool for the job.
    Miles : The thing with eval is that when it seems like a viable solution, 99.9% of the time, it's an indicator that you're approaching the problem in the wrong way. In this case, it's unlikely that the OP really should be getting a function in the current scope by name; instead, the functions should probably be stored in an Object so that they can be directly looked up by key.
    Jon Benedicto : I get your point - but I wouldn't let that make eval "evil" :-) just in this instance, the OP should probably think up a better design.
  • I just did a quick test in Firebug and I was able to get the function from the name by simply eval()ing the name... I feel dirty using eval(), but it seems to get the job done here quite nicely.

    var myFunctionPtr = eval(func_name);
    
    Max Schmeling : Can you pass parameters in that way?
    Rick Copeland : Certainly -- once you have myFunctionPtr, you use it as a regular function.
    mkoryak : or you can use window[func_name] which gets the job done too.
    Rick Copeland : @mkoryak -- not if the function you're looking up is not globally defined
    Miles : If the function you're looking up is not globally defined, you should put it into an object so that you can look it up by a key.
  • A safe way to do is to sandbox the alleged function while testing its type:

    function isFunction(expr) {
        function sandboxTemplate() {
            var window, document, alert; // etc.
    
            try {
                return typeof $expr$ == "function";
            } catch (e) {
                return false;
            }
        }
    
        try {
            var sandbox = new Function(
                sandboxTemplate.toString().replace("$expr$", expr)
                + "return sandboxTemplate()");
            return sandbox();
        } catch (e) {
            return false;
        }
    }
    
    function test(expr) {
        document.write("<div>\"" + expr + "\" <b>is "
            + (isFunction(expr) ? "" : "not ")
            + "</b>a function</div>");
    }
    
    /* Let's do some testing */
    
    function realFunction() {
    }
    
    test("realFunction");       // exists!
    test("notHere");            // non-existent
    test("alert('Malicious')"); // attempt to execute malicious code!
    test("syntax error {");     // attempt to blow us up!
    

    The output:

    • "realFunction" is a function
    • "notHere" is not a function
    • "alert('Malicious')" is not a function
    • "syntax error {" is not a function

    The sandboxing code could be written in a more concise manner but I like using "template" functions instead of embedding JS code as string literals.

    And oh, this does it nicely without using eval -- though one can argue that using a Function constructor is no different than an eval.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.