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

时间:2021-12-15 16:57:49

In JavaScript, if I have a string in a variable, is there a way to get a reference to the function object which has that matching name? Note that jQuery is available to me so I can use any of its helper methods also.

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

For example:

例如:

myFunction = function(){};

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

Thanks

谢谢

9 个解决方案

#1


60  

if you know that its a global function you can use:

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

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

Otherwise replace window with the parent object containing the function.

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

#2


21  

I just did a quick test in Firebug and I was able to get the function from the name by simply eval()ing the name... I feel dirty using eval(), but it seems to get the job done here quite nicely.

我只是在Firebug中做了一个快速测试,我只能通过eval()名称来获取名称中的函数...我觉得使用eval()很脏,但它似乎很好地完成了这里的工作。

var myFunctionPtr = eval(func_name);

#3


15  

This is never a preferred approach. Instead of keeping the function name in func_name, you could have kept the reference to a function just as successfully in something like func_to_call.

这绝不是首选方法。您可以像func_to_call一样成功地保留对函数的引用,而不是将函数名保留在func_name中。

If you absolutely require to keep the function reference as a string, you would typically use a hash table to map an arbitrary name to a variable (JS has first-class functions which makes it possible)

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

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

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

Fiddled (I don't know why, it's a such a tiny script :)

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

It was suggested that you use eval(func_name) - however this could quickly get out of control because of JS scoping.

有人建议您使用eval(func_name) - 但是由于JS作用域,这很快就会失控。

You have also declared your myFunction = function(){}; as a global variable. On one hand, it lets you reference it as window[func_name] but on the other hand it pollutes the global scope.

您还声明了myFunction = function(){};作为一个全局变量。一方面,它允许您将其作为窗口[func_name]引用,但另一方面它会污染全局范围。

#4


9  

this[func_name] should give you the function.

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

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

#5


5  

It depends on where and how the function is (or isn't) declared.

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

If it's a global and not declared via let name = ... or const name = ... syntax (and it's not a class constructor declared with class), you can check by looking for it as a property on the global object. (Those caveats are all ES2015 things; more below.) You can get a reference to the global object via this in loose mode at global scope; browsers also give you a global called window. So assuming a browser:

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

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

If it might not be a global, but rather is just in scope because your code closes over it, or if it was created using one of those ES2015 mechanisms I mentioned, there's really no good way to check other than eval:

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

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

Using eval is a last resort, and you must only use it with strictly-controlled input. But when you have to, and you have strictly-controlled input, it's fine.

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


About the ES2015 caveats:

关于ES2015警告:

The new let, const, and class are very interesting beasties: When used at global scope, they create globals, but they don't create properties on the global object. As of ES2015, although all properties of the global object are globals, not all globals are properties of the global object. It's all part of trying to rein in vastly-polluted global namespace and also bring greater security to the JavaScript binding model. (Now that we have true modules.)

新的let,const和class是非常有趣的事物:当在全局范围内使用时,它们会创建全局变量,但它们不会在全局对象上创建属性。从ES2015开始,虽然全局对象的所有属性都是全局对象,但并非所有全局对象都是全局对象的属性。这是试图控制受到严重污染的全局命名空间并为JavaScript绑定模型带来更高安全性的所有部分。 (现在我们有了真正的模块。)

So (note that this will only run in cutting-edge browsers):

所以(请注意,这只会在最先进的浏览器中运行):

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

Output on cutting-edge browsers:

最先进的浏览器输出:

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

Note: Some transpilers don't enforce this rigorously, so if you see different results in transpiled code, don't be surprised.

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

#6


4  

Use eval:

使用eval:

myFunction = function(){};

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

#7


3  

A safe way to do is to sandbox the alleged function while testing its type:

一种安全的方法是在测试其类型时对所谓的函数进行沙箱化:

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!

The output:

输出:

  • "realFunction" is a function
  • “realFunction”是一个函数
  • "notHere" is not a function
  • “notHere”不是一个功能
  • "alert('Malicious')" is not a function
  • “警报('恶意')”不是一个功能
  • "syntax error {" is not a function
  • “语法错误{”不是一个函数

The sandboxing code could be written in a more concise manner but I like using "template" functions instead of embedding JS code as string literals.

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

And oh, this does it nicely without using eval -- though one can argue that using a Function constructor is no different than an eval.

哦,这很好地不使用eval - 尽管可以说使用Function构造函数与eval没有区别。

#8


0  

found the function and then call them

找到该功能,然后调用它们

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

#9


0  

For NodeJs

对于NodeJs

Write your functions in a separate file and export them and use with name reference of that to call them, Like

将您的函数写在一个单独的文件中并导出它们并使用它的名称引用来调用它们,Like

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

Use function defined in functions.js in index.js :

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

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

OUTPUT :

输出:

> node index.js
> function ONE called

#1


60  

if you know that its a global function you can use:

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

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

Otherwise replace window with the parent object containing the function.

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

#2


21  

I just did a quick test in Firebug and I was able to get the function from the name by simply eval()ing the name... I feel dirty using eval(), but it seems to get the job done here quite nicely.

我只是在Firebug中做了一个快速测试,我只能通过eval()名称来获取名称中的函数...我觉得使用eval()很脏,但它似乎很好地完成了这里的工作。

var myFunctionPtr = eval(func_name);

#3


15  

This is never a preferred approach. Instead of keeping the function name in func_name, you could have kept the reference to a function just as successfully in something like func_to_call.

这绝不是首选方法。您可以像func_to_call一样成功地保留对函数的引用,而不是将函数名保留在func_name中。

If you absolutely require to keep the function reference as a string, you would typically use a hash table to map an arbitrary name to a variable (JS has first-class functions which makes it possible)

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

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

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

Fiddled (I don't know why, it's a such a tiny script :)

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

It was suggested that you use eval(func_name) - however this could quickly get out of control because of JS scoping.

有人建议您使用eval(func_name) - 但是由于JS作用域,这很快就会失控。

You have also declared your myFunction = function(){}; as a global variable. On one hand, it lets you reference it as window[func_name] but on the other hand it pollutes the global scope.

您还声明了myFunction = function(){};作为一个全局变量。一方面,它允许您将其作为窗口[func_name]引用,但另一方面它会污染全局范围。

#4


9  

this[func_name] should give you the function.

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

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

#5


5  

It depends on where and how the function is (or isn't) declared.

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

If it's a global and not declared via let name = ... or const name = ... syntax (and it's not a class constructor declared with class), you can check by looking for it as a property on the global object. (Those caveats are all ES2015 things; more below.) You can get a reference to the global object via this in loose mode at global scope; browsers also give you a global called window. So assuming a browser:

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

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

If it might not be a global, but rather is just in scope because your code closes over it, or if it was created using one of those ES2015 mechanisms I mentioned, there's really no good way to check other than eval:

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

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

Using eval is a last resort, and you must only use it with strictly-controlled input. But when you have to, and you have strictly-controlled input, it's fine.

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


About the ES2015 caveats:

关于ES2015警告:

The new let, const, and class are very interesting beasties: When used at global scope, they create globals, but they don't create properties on the global object. As of ES2015, although all properties of the global object are globals, not all globals are properties of the global object. It's all part of trying to rein in vastly-polluted global namespace and also bring greater security to the JavaScript binding model. (Now that we have true modules.)

新的let,const和class是非常有趣的事物:当在全局范围内使用时,它们会创建全局变量,但它们不会在全局对象上创建属性。从ES2015开始,虽然全局对象的所有属性都是全局对象,但并非所有全局对象都是全局对象的属性。这是试图控制受到严重污染的全局命名空间并为JavaScript绑定模型带来更高安全性的所有部分。 (现在我们有了真正的模块。)

So (note that this will only run in cutting-edge browsers):

所以(请注意,这只会在最先进的浏览器中运行):

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

Output on cutting-edge browsers:

最先进的浏览器输出:

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

Note: Some transpilers don't enforce this rigorously, so if you see different results in transpiled code, don't be surprised.

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

#6


4  

Use eval:

使用eval:

myFunction = function(){};

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

#7


3  

A safe way to do is to sandbox the alleged function while testing its type:

一种安全的方法是在测试其类型时对所谓的函数进行沙箱化:

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!

The output:

输出:

  • "realFunction" is a function
  • “realFunction”是一个函数
  • "notHere" is not a function
  • “notHere”不是一个功能
  • "alert('Malicious')" is not a function
  • “警报('恶意')”不是一个功能
  • "syntax error {" is not a function
  • “语法错误{”不是一个函数

The sandboxing code could be written in a more concise manner but I like using "template" functions instead of embedding JS code as string literals.

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

And oh, this does it nicely without using eval -- though one can argue that using a Function constructor is no different than an eval.

哦,这很好地不使用eval - 尽管可以说使用Function构造函数与eval没有区别。

#8


0  

found the function and then call them

找到该功能,然后调用它们

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

#9


0  

For NodeJs

对于NodeJs

Write your functions in a separate file and export them and use with name reference of that to call them, Like

将您的函数写在一个单独的文件中并导出它们并使用它的名称引用来调用它们,Like

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

Use function defined in functions.js in index.js :

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

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

OUTPUT :

输出:

> node index.js
> function ONE called