Get JavaScript function-object from its name as a string?

Javascript

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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);

Solution 3 - Javascript

This is never a preferred approach. Instead of keeping the function name in func_name, you could have kept the reference to a function just as successfully in something like func_to_call.

If you absolutely require to keep the function reference as a string, you would typically use a hash table to map an arbitrary name to a variable (JS has first-class functions which makes it possible)

myFunction = function(){};   
var obj = {func_name: myFunction};

obj['func_name']();//executes the function

Fiddled (I don't know why, it's a such a tiny script :)

It was suggested that you use eval(func_name) - however this could quickly get out of control because of JS scoping.

You have also declared your myFunction = function(){}; as a global variable. On one hand, it lets you reference it as window[func_name] but on the other hand it pollutes the global scope.

Solution 4 - Javascript

this[func_name] should give you the function.

var myfunc = this[func_name];
myfunc();

Solution 5 - Javascript

It depends on where and how the function is (or isn't) declared.

If it's a global and not declared via let name = ... or const name = ... syntax (and it's not a class constructor declared with class), you can check by looking for it as a property on the global object. (Those caveats are all ES2015 things; more below.) You can get a reference to the global object via this in loose mode at global scope; browsers also give you a global called window. So assuming a browser:

if (typeof window[func_name] === "function") {
    // ....
}

If it might not be a global, but rather is just in scope because your code closes over it, or if it was created using one of those ES2015 mechanisms I mentioned, there's really no good way to check other than eval:

if (eval("typeof " + func_name) === "function") {
    // ....
}

Using eval is a last resort, and you must only use it with strictly-controlled input. But when you have to, and you have strictly-controlled input, it's fine.


About the ES2015 caveats:

The new let, const, and class are very interesting beasties: When used at global scope, they create globals, but they don't create properties on the global object. As of ES2015, although all properties of the global object are globals, not all globals are properties of the global object. It's all part of trying to rein in vastly-polluted global namespace and also bring greater security to the JavaScript binding model. (Now that we have true modules.)

So (note that this will only run in cutting-edge browsers):

// Global scope, in a browser (because I used `window` and `document.body`) that
// implements this aspect of ES2015 (as I write this, Firefox's SpiderMonkey
// doesn't, Chrome's V8 does on the latest Chrome; expect SpiderMonkey and IE
// to catch up pretty quick (didn't test IE Edge, maybe it's already there)

// Strict mode isn't required for this behavior, but for the moment V8 only
// supports the block-scoped constructs in strict mode.
"use strict";
let tbody = setup();

// Old-fashioned var: Creates a property on the global object, so
// we get "function, function"
var f1 = function() { /*...*/ };
result("var declaration", typeof f1, typeof window["f1"]);

// Function declaration: Creates a property on the global object, so
// "function, function"
function f2() {}
result("function declaration", typeof f2, typeof window["f2"]);

// `let` declaration: Doesn't create property on global object, so
// "function, undefined"
let f3 = function() { /*...*/ };
result("let declaration", typeof f3, typeof window["f3"]);

// `const` declaration: Doesn't create property on global object, so
// "function, undefined"
const f4 = function() { /*...*/ };
result("const declaration", typeof f4, typeof window["f4"]);

// `class` declaration: Doesn't create property on global object, so
// "function, undefined"
class C1 {}
result("class declaration", typeof C1, typeof window["C1"]);

function setup() {
  document.body.insertAdjacentHTML(
    "beforeend",
    "<table>" +
    "<thead>" +
    "<tr><th>test</th><th>global</th><th>prop</th></tr>" +
    "</thead>" +
    "<tbody></tbody>" +
    "</table>"
  );
  return document.body.querySelector("tbody");
}

function result(label, direct, win) {
  tbody.insertAdjacentHTML(
    "beforeend",
    "<tr><td>" + [label, direct, win].join("</td><td>") + "</td></tr>"
  );
}

body {
  font-family: sans-serif;
}
table {
  border-collapse: collapse;
}
th, td {
  border: 1px solid #ddd;
  padding: 4px 8px;
}

Output on cutting-edge browsers:

+----------------------+------------+-----------+
|         test         |   global   |   prop    |
+----------------------+------------+-----------+
| var declaration      |  function  | function  |
| function declaration |  function  | function  |
| let declaration      |  function  | undefined |
| const declaration    |  function  | undefined |
| class declaration    |  function  | undefined |
+----------------------+------------+-----------+

Note: Some transpilers don't enforce this rigorously, so if you see different results in transpiled code, don't be surprised.

Solution 6 - Javascript

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.

Solution 7 - Javascript

Use eval:

myFunction = function(){};

var func_name = "myFunction";
var myFunctionPtr = eval(func_name);

Solution 8 - Javascript

found the function and then call them

autoCallBack : function(_action){
            $(".module").each(function(){
                var modulName = $(this).attr("id");
                if( isFunction(modulName) ){
                    eval(modulName)();
                }
            });
        }

isFunction : function(_functionName){
        try {
            eval(_functionName);
        } catch (error) {
            return false;
        }
    return true;
}

Solution 9 - Javascript

For NodeJs

Write your functions in a separate file and export them and use with name reference of that to call them, Like

//    functions.js
var funcOne = function(){
                   console.log('function ONE called')
              }
module.exports={
    //  name_exported : internal_name
    funcOne : funcOne
}

Use function defined in functions.js in index.js :

//    index.js
var methods = require('./functions.js')   // path to functions.js
methods['funcOne']()

OUTPUT :

> node index.js
> function ONE called

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsolsbergView Question on Stackoverflow
Solution 1 - JavascriptmkoryakView Answer on Stackoverflow
Solution 2 - JavascriptrmeadorView Answer on Stackoverflow
Solution 3 - JavascriptOlegView Answer on Stackoverflow
Solution 4 - JavascriptMax SchmelingView Answer on Stackoverflow
Solution 5 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 6 - JavascriptAtes GoralView Answer on Stackoverflow
Solution 7 - JavascriptJon BenedictoView Answer on Stackoverflow
Solution 8 - JavascriptMajid GolshadiView Answer on Stackoverflow
Solution 9 - JavascriptRupinder SinghView Answer on Stackoverflow