2009-04-21 86 views
36

在JavaScript中,如果我在变量中有一个字符串,是否有一种方法来获取具有匹配名称的函数对象的引用?请注意,jQuery对我来说是可用的,所以我可以使用它的任何helper方法。从字符串名称中获取JavaScript函数对象?

例如:

myFunction = function(){}; 

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

感谢

回答

58

,如果你知道它是一个全球性的功能,你可以使用:

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

否则与包含该函数的父对象替换窗口

+5

要传递参数:窗口[FUNC_NAME](myArg1,myArg2); – mpemburn 2014-11-03 20:06:20

9

这[func_name]应该给你的功能。

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

我只是试图在Firebug中,它没有工作。也许它在网页中表现不同? – rmeador 2009-04-21 15:36:46

+0

这取决于你的功能在哪里定义。如果函数没有在'this'上定义,那么它将不会找到它。您可能需要尝试窗口[func_name]或Some.Other.Object [func_name] – 2009-04-21 15:38:57

4

使用eval:

myFunction = function(){}; 

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

eval是邪恶的。不要使用eval – mkoryak 2009-04-21 15:47:32

+3

为什么?你能举出一些很好的理由。 – 2009-04-21 16:04:49

21

我只是做了一个快速测试在Firebug,我能够通过简单eval()从名字得到函数荷兰国际集团的名字......我觉得脏使用eval() ,但它似乎很好地完成了这项工作。

var myFunctionPtr = eval(func_name); 
3

一种安全的方式做的是沙箱涉嫌功能在测试它的类型:

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”不是功能
  • “警报(‘恶意’)” 不是函数
  • “语法错误{” 不是函数

的沙盒代码可以以更简洁的方式被写入,但我喜欢使用“模板”功能而不是将JS代码嵌入到字符串文字中。

哦,这样做很好,不需要使用eval - 虽然人们可以争辩说使用Function构造函数与eval没有区别。

14

这永远不是首选的方法。除了保留func_name中的函数名称之外,您可以在func_to_call之类的东西中保留对函数的引用。

如果你绝对需要保持函数引用作为字符串,您通常会使用一个哈希表来任意名称映射到一个变量(JS拥有一流的功能,这使得它有可能)

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

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

Fiddled(我不知道为什么,这是一个这么小的脚本:)

有人建议你使用eval(func_name) - 然而,这很快就可能失去,因为JS的作用域的控制。

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

0

发现功能,然后打电话给他们

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

这取决于其中函数如何是(或没有)声明。

如果它是一个全球通过let name = ...const name = ...语法未声明(这不是与class声明的类的构造函数),你可以通过寻找它作为全局对象上的属性进行检查。 (这些注意事项都是ES2015的东西;更多内容请参阅下文。)您可以在全局范围内以松散模式通过this获得对全局对象的引用;浏览器也给你一个全球性的号码window。因此,假设一个浏览器:

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

如果可能是一个全球性的,而仅仅是在范围,因为你的代码关闭了它,或者如果它是用的我提到的那些ES2015机制之一创建的,有真的没有什么好办法比eval检查其他:

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

使用eval是最后的手段,你必须与严格控制的输入使用。但是,如果你需要,并且你严格控制了输入,那很好。


关于ES2015注意事项:

letconstclass是非常有趣的小动物:当在全局范围内使用,他们创造全局变量,但他们创建属性全局对象。从ES2015开始,尽管全局对象的所有属性都是全局对象,但并非所有全局对象都是全局对象的属性。这是试图控制严重污染的全局名称空间的一部分,并且为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; 
 
}

输出尖端的浏览器:

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

注:有些译员不会严格执行此操作,所以如果您在译码中看到不同的结果,请不要感到惊讶。

0

对于的NodeJS

写你的函数在一个单独的文件和导出,然后用该名称参考使用打电话给他们,就像在functions.js定义

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

使用功能 in index.js

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

OUTPUT:

> node index.js 
> function ONE called