devios1
devios1

Reputation: 38025

Create a JavaScript function dynamically from a string name

Given a string classname, I want to dynamically create a new JavaScript function named after that string that can be used to instantiate objects.

I've tried using eval() but for some reason the declared function does not appear in the global (window) scope.

eval( "function " + classname + "() {}" );
window[ classname ]; // => undefined

Is there a way I can dynamically create a new function named after a string?

Or, alternatively, give me some way to reference the created function after creating it via eval. Interestingly it appears as a local variable when I debug it in Safari.

Update:

Got it! Of course it's obvious, I just use eval again to create the instance:

var myInstance = eval( "new " + classname );
myInstance.constructor.name; // => classname (yay)

This should work in my case because I only need to create one instance of the class right after it's declared. For the general case though see Pointy's answer.

Upvotes: 10

Views: 18840

Answers (4)

Linh Dam
Linh Dam

Reputation: 2219

In case you don't want to create new functions based on some string, but based on another similar function: (this might not be a good example but hope you can get the idea)

function createListOfFunctions(functionNameList) {
  resultFunctions = {};

  // Loop all names to create a list of functions with those names
  $.each(functionNameList, function(index, functionName) {
    resultFunctions[functionName] = _createFunction(functionName);
  });

  return resultFunctions;
}

function _createFunction(name) {
  return function(anotherNameToCompare) {
    // customize this funciton whatever you like
    return name == anotherNameToCompare;
  };
}


// USAGE:
functionNameList = ['stack', 'overflow'];
result = createListOfFunctions(functionNameList); // result = { stack: function(name) {...}, overflow: function(name) {...} }

result.stack('stack'); // true
result.stack('not stack'); // false
result.overflow('overflow'); // true

Upvotes: 2

user797257
user797257

Reputation:

function registerFunction(functionBody) {
         "use strict";
         var script = document.createElement("script");
         script.innerHTML = "function " + functionBody;
         document.body.appendChild(script);
}
registerFunction("fooBar(x, y) { return x + y; }");
fooBar(1, 2); // will give you 3

Although this is essentially the same as eval() but it will register the function in the domain of the current page. You can later remove this script element, or reuse it for other functions.

Upvotes: 7

Kevin Boucher
Kevin Boucher

Reputation: 16675

Try this:

var classname = "myFunction";

window[ classname ] = function () {};

alert( window[ classname ] ); // => undefined

Upvotes: 2

Pointy
Pointy

Reputation: 413737

Yes:

window[classname] = function() { ... };

Now, in honesty, that's not exactly like what you were attempting, but it's pretty close. When you instantiate a function via a function expression like that, and without a name, the function can't refer to itself except via the name in the outer scope (in this case, the global scope).

If that's important, what you could do is this: create the function with some stock "internal" name, and then assign it to the global name:

function secretName() { ... }

window[classname] = secretName;

Upvotes: 12

Related Questions