从string的名称获取JavaScript函数对象?

在JavaScript中,如果我在variables中有一个string,有没有办法获得具有匹配名称的函数对象的引用? 请注意,jQuery对我来说是可用的,所以我可以使用它的任何helper方法。

例如:

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

谢谢

如果你知道它的全局函数,你可以使用:

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

否则,用包含函数的父对象replace窗口

我只是在Firebug中做了一个快速的testing,通过简单的eval()名字就可以得到名字的function…我用eval()感觉很脏,但是看起来这个工作很好的完成了。

 var myFunctionPtr = eval(func_name); 

这不是一个首选的方法。 而不是保留func_name的函数名,你可以像func_to_call一样保持对函数的引用。

如果你绝对需要将函数引用保持为一个string,那么通常使用一个散列表来将一个任意名称映射到一个variables(JS具有使之成为可能的一类函数)

 myFunction = function(){}; var obj = {func_name: myFunction}; obj['func_name']();//executes the function 

小提琴 (我不知道为什么,这是一个如此微小的脚本:)

有人build议你使用eval(func_name) – 但是由于JS范围的限制,这可能会很快失去控制。

你也宣布你的myFunction = function(){}; 作为一个全球variables。 一方面,它可以让你把它作为window[func_name]引用,但是另一方面它会污染全局范围。

这[func_name]应该给你的function。

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

这取决于函数在哪里以及如何 (或不)被声明。

如果它是一个全局variables而不是通过let name = ...const name = ...语法来声明的(并且它不是用类声明的类构造函数),那么可以通过查找它作为全局对象的属性来进行检查。 (这些注意事项都是ES2015的东西;更多的内容在下面)。您可以通过全局范围的松散模式获得对全局对象的引用; 浏览器也给你一个全局调用window 。 所以假设一个浏览器:

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

如果它可能不是一个全局的,而只是在范围内,因为你的代码closures它,或者如果它是使用我提到的ES2015机制之一创build的,那么真的没有什么好的方法来检查除了eval

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

使用eval是最后的手段,您只能使用严格控制的input。 但是当你需要,而且你严格控制了input的时候,没关系。


关于ES2015的注意事项:

新的letconstclass是非常有趣的。在全局范围使用时,它们创build全局对象,但是它们不会在全局对象上创build属性。 从ES2015开始,尽pipe全局对象的所有属性都是全局对象,但并非所有全局对象都是全局对象的属性。 这是试图控制严重污染的全局命名空间的一部分,同时也为JavaScript绑定模型带来了更高的安全性。 (现在我们有了真正的模块。)

所以(请注意,这只能在尖端的浏览器上运行):

 // 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; } 

使用评估:

 myFunction = function(){}; var func_name = "myFunction"; var myFunctionPtr = eval(func_name); 

一个安全的方法是在testing它的types的时候对所谓的函数进行沙箱处理:

 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! 

输出:

  • “realFunction” 一个函数
  • “notHere” 不是一个函数
  • “alert('恶意')” 不是一个函数
  • “语法错误{” 不是一个函数

沙箱代码可以用更简洁的方式编写,但我喜欢使用“模板”函数,而不是将JS代码作为string文本embedded。

而且,哦,这很好地使用eval – 虽然可以争辩说,使用Function构造函数与eval没有区别。

find了function,然后打电话给他们

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

对于NodeJs

把你的函数写在一个单独的文件中,然后导出它们,并使用名称引用来调用它们

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

使用index.js中的functions.js中定义的函数

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

输出:

 > node index.js > function ONE called