从名称中获取JavaScript函数对象作为字符串?

sol*_*erg 46 javascript

在JavaScript中,如果我在变量中有一个字符串,有没有办法获得对具有该匹配名称的函数对象的引用?请注意,jQuery可供我使用,因此我也可以使用它的任何辅助方法.

例如:

myFunction = function(){};

var func_name = "myFunction";
var myFunctionPtr = ???  //how to get the function from the name
Run Code Online (Sandbox Code Playgroud)

谢谢

mko*_*yak 70

如果您知道它是一个全局函数,您可以使用:

var functPtr = window[func_name];
//functPtr()
Run Code Online (Sandbox Code Playgroud)

否则用包含该函数的父对象替换window.

  • 传递参数:window [func_name](myArg1,myArg2); (7认同)

rme*_*dor 21

我只是在Firebug中做了一个快速测试,我只是通过简单eval()的命名从名称中获取了这个功能......我感觉很脏eval(),但是它似乎很好地完成了这项工作.

var myFunctionPtr = eval(func_name);
Run Code Online (Sandbox Code Playgroud)

  • 当然——一旦你有了 myFunctionPtr,你就可以将它用作常规函数。 (2认同)
  • @mkoryak - 如果您正在查找的功能未全局定义,则不会 (2认同)

o.v*_*.v. 16

这绝不是首选方法.func_name您可以保持对函数的引用,而不是保持函数名称func_to_call.

如果您绝对需要将函数引用保留为字符串,则通常会使用哈希表将任意名称映射到变量(JS具有使其成为可能的第一类函数)

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

obj['func_name']();//executes the function
Run Code Online (Sandbox Code Playgroud)

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

有人建议你使用eval(func_name)- 但是由于JS范围的限制,这很快就会失控.

您还将自己声明myFunction = function(){};为全局变量.一方面,它允许您引用它,window[func_name]但另一方面它污染全局范围.

  • +1 这个解决方案有效,令人惊讶的是从未被投票。我发现它对于我的用例来说是最优雅的。 (2认同)

Max*_*ing 10

这个[func_name]应该给你这个功能.

var myfunc = this[func_name];
myfunc();
Run Code Online (Sandbox Code Playgroud)


T.J*_*der 6

它取决于声明函数的位置方式.

如果它是全局的而不是声明的via let name = ...const name = ...语法(并且它不是声明的类构造函数class),则可以通过在全局对象上查找它作为属性来进行检查.(这些警告都是ES2015的内容;更多内容.)您可以通过this全局范围内的松散模式获取对全局对象的引用; 浏览器还为您提供全局调用window.所以假设一个浏览器:

if (typeof window[func_name] === "function") {
    // ....
}
Run Code Online (Sandbox Code Playgroud)

如果它可能不是全局的,而是仅仅在范围内,因为你的代码关闭它,或者它是使用我提到的那些ES2015机制之一创建的,那么除了以下之外没有其他方法可以检查eval:

if (eval("typeof " + func_name) === "function") {
    // ....
}
Run Code Online (Sandbox Code Playgroud)

使用eval是最后的手段,您只能使用严格控制的输入.但是当你必须,并且你有严格控制的输入时,它没关系.


关于ES2015警告:

新的let,constclass非常有趣的小动物:当在全局范围内使用,他们创造全局变量,但他们创建全局对象的属性.从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>"
  );
}
Run Code Online (Sandbox Code Playgroud)
body {
  font-family: sans-serif;
}
table {
  border-collapse: collapse;
}
th, td {
  border: 1px solid #ddd;
  padding: 4px 8px;
}
Run Code Online (Sandbox Code Playgroud)

在尖端浏览器上输出:

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

注意:有些转换器不会严格执行此操作,因此如果您在转换后的代码中看到不同的结果,请不要感到惊讶.