从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的注意事项:
新的let
, const
和class
是非常有趣的。在全局范围使用时,它们创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