从字符串名称动态创建 JavaScript 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12964262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 17:31:27  来源:igfitidea点击:

Create a JavaScript function dynamically from a string name

javascriptclassfunction

提问by devios1

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

给定一个 string classname,我想动态创建一个以该字符串命名的新 JavaScript 函数,该函数可用于实例化对象。

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

我试过使用eval()但由于某种原因声明的函数没有出现在全局(窗口)范围内。

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.

或者,在通过eval. 有趣的是,当我在 Safari 中调试它时,它显示为一个局部变量。

Update:

更新:

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

知道了!当然很明显,我只是eval再次使用来创建实例:

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.

这应该适用于我的情况,因为我只需要在声明后立即创建该类的一个实例。对于一般情况,请参阅 Pointy 的回答。

回答by Pointy

Yes:

是的:

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

Now, in honesty, that's not exactlylike what you were attempting, but it's pretty close. When you instantiate a function via a functionexpressionlike 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).

现在,老实说,这与您尝试的并不完全一样,但非常接近。当您通过这样的function表达式实例化一个函数并且没有名称时,该函数不能引用自身,除非通过外部作用域(在本例中为全局作用域)中的名称。

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;

回答by devios1

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.

虽然这本质上是一样的,eval()但是它会在当前页面的域中注册函数。您可以稍后删除此脚本元素,或将其重新用于其他功能。

回答by Kevin Boucher

Try this:

试试这个:

var classname = "myFunction";

window[ classname ] = function () {};

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

回答by Linh Dam

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