简体   繁体   English

当我将其名称作为字符串时如何执行 JavaScript function

[英]How to execute a JavaScript function when I have its name as a string

I have the name of a function in JavaScript as a string.我在 JavaScript 中有一个 function 作为字符串的名称。 How do I convert that into a function pointer so I can call it later?如何将其转换为 function 指针以便稍后调用它?

Depending on the circumstances, I may need to pass various arguments into the method too.根据具体情况,我可能也需要将各种 arguments 传递到方法中。

Some of the functions may take the form of namespace.namespace.function(args[...]) .一些函数可能采用namespace.namespace.function(args[...])的形式。

Don't use eval unless you absolutely, positively have no other choice.不要使用eval除非你绝对没有其他选择。

As has been mentioned, using something like this would be the best way to do it:如前所述,使用这样的方法是最好的方法:

window["functionName"](arguments);

That, however, will not work with a namespace'd function:但是,这不适用于命名空间的函数:

window["My.Namespace.functionName"](arguments); // fail

This is how you would do that:这是你将如何做到这一点:

window["My"]["Namespace"]["functionName"](arguments); // succeeds

In order to make that easier and provide some flexibility, here is a convenience function:为了使这更容易并提供一些灵活性,这里有一个方便的功能:

function executeFunctionByName(functionName, context /*, args */) {
  var args = Array.prototype.slice.call(arguments, 2);
  var namespaces = functionName.split(".");
  var func = namespaces.pop();
  for(var i = 0; i < namespaces.length; i++) {
    context = context[namespaces[i]];
  }
  return context[func].apply(context, args);
}

You would call it like so:你会这样称呼它:

executeFunctionByName("My.Namespace.functionName", window, arguments);

Note, you can pass in whatever context you want, so this would do the same as above:请注意,您可以在任何您想要的上下文中传递,因此这将与上述相同:

executeFunctionByName("Namespace.functionName", My, arguments);

Just thought I'd post a slightly altered version of Jason Bunting's very helpful function .只是想我会发布一个稍微改动过的Jason Bunting 非常有用的功能的版本

First, I have simplified the first statement by supplying a second parameter to slice() .首先,我通过向slice()提供第二个参数简化了第一个语句。 The original version was working fine in all browsers except IE.原始版本在除 IE 之外的所有浏览器中都能正常工作。

Second, I have replaced this with context in the return statement;其次,我在 return 语句中用上下文替换了 otherwise, this was always pointing to window when the target function was being executed.否则,当执行目标函数时, this总是指向window

function executeFunctionByName(functionName, context /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(context, args);
}

The answer to this other question shows you how to do that: Javascript equivalent of Python's locals()?另一个问题的答案向您展示了如何做到这一点: Javascript 等效于 Python 的 locals()?

Basically, you can say基本上,你可以说

window["foo"](arg1, arg2);

or as many others have suggested, you can just use eval:或者正如许多其他人所建议的那样,您可以只使用 eval:

eval(fname)(arg1, arg2);

although this is extremely unsafe unless you're absolutely sure about what you're eval-ing.尽管这是非常不安全的,除非您绝对确定要评估的内容。

I think an elegant way of doing this is by defining your functions in a hash object.我认为这样做的一种优雅方法是在哈希对象中定义您的函数。 Then you can have a reference to those functions from the hash using the string.然后,您可以使用字符串从散列中引用这些函数。 eg例如

var customObject = {
  customFunction: function(param){...}
};

Then you can call:然后你可以调用:

customObject['customFunction'](param);

Where customFunction will be a string matching a function defined in your object.其中 customFunction 将是匹配对象中定义的函数的字符串。

UPDATE更新

It seems that this answer was helpful for many fellow coders out there so here goes an updated version.似乎这个答案对那里的许多编码人员很有帮助,所以这里有一个更新的版本。

With ES6 you can additionally use Computed Property Names which will allow you to avoid magic strings.使用 ES6,您还可以使用计算属性名称,这将允许您避免魔术字符串。

 const FunctionNames = Object.freeze({ FirstFunction: "firstFunction", SecondFunction: "secondFunction" }); ... var customObject = { [FunctionNames.FirstFunction]: function(param){...}, [FunctionNames.SecondFunction]: function(param){...} }; ... customObject[FunctionNames.FirstFunction](param);

Could you not just do this:你能不能不这样做:

var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();

You can also execute any other JavaScript using this method.您还可以使用此方法执行任何其他 JavaScript。

With ES6 you could to access class methods by name:使用 ES6,您可以按名称访问类方法:

class X {
  method1(){
    console.log("1");
  }
  method2(){
    this['method1']();
    console.log("2");
  }
}
let x  = new X();
x['method2']();

the output would be:输出将是:

1
2

Two things:两件事情:

  • avoid eval, it's terribly dangerous and slow避免使用 eval,它非常危险且缓慢

  • secondly it doesn't matter where your function exists, "global" -ness is irrelevant.其次,你的函数在哪里并不重要,“全局”是无关紧要的。 xyfoo() can be enabled through xy['foo']() or x['y']['foo']() or even window['x']['y']['foo']() . xyfoo()可以通过xy['foo']()x['y']['foo']()甚至window['x']['y']['foo']()启用。 You can chain indefinitely like this.你可以像这样无限期地链接。

All the answers assume that the functions can be accessed through global scope (window).所有答案都假设可以通过全局范围(窗口)访问这些函数。 However, the OP did not make this assumption.但是,OP 没有做出这个假设。

If the functions live in a local scope (aka closure) and are not referenced by some other local object, bad luck: You have to use eval() AFAIK, see dynamically call local function in javascript如果函数存在于局部作用域(又名闭包)中并且未被其他局部对象引用,那么运气不好:您必须使用eval() AFAIK,请参阅在 javascript 中动态调用本地函数

Depending on where you are you can also use:根据您所在的位置,您还可以使用:

this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();

or, in nodejs或者,在 nodejs 中

global["funcname"]()

You just need convert your string to a pointer by window[<method name>] .您只需要通过window[<method name>]将字符串转换为指针。 example:例子:

var function_name = "string";
function_name = window[function_name];

and now you can use it like a pointer.现在你可以像指针一样使用它。

Here is my contribution to Jason Bunting's / Alex Nazarov's excellent answers, where I include error checking requested by Crashalot.这是我对 Jason Bunting/Alex Nazarov 出色答案的贡献,其中包括 Crashalot 要求的错误检查。

Given this (contrived) preamble:鉴于这个(人为的)序言:

a = function( args ) {
    console.log( 'global func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] );
    }
};
ns = {};
ns.a = function( args ) {
    console.log( 'namespace func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] ); 
    }
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};

then the following function:然后是以下函数:

function executeFunctionByName( functionName, context /*, args */ ) {
    var args, namespaces, func;

    if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }

    if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }

    if( typeof context !== 'undefined' ) { 
        if( typeof context === 'object' && context instanceof Array === false ) { 
            if( typeof context[ functionName ] !== 'function' ) {
                throw context + '.' + functionName + ' is not a function';
            }
            args = Array.prototype.slice.call( arguments, 2 );

        } else {
            args = Array.prototype.slice.call( arguments, 1 );
            context = window;
        }

    } else {
        context = window;
    }

    namespaces = functionName.split( "." );
    func = namespaces.pop();

    for( var i = 0; i < namespaces.length; i++ ) {
        context = context[ namespaces[ i ] ];
    }

    return context[ func ].apply( context, args );
}

will allow you to call a javascript function by name stored in a string, either namespaced or global, with or without arguments (including Array objects), providing feedback on any errors encountered (hopefully catching them).将允许您通过存储在字符串中的名称调用 javascript 函数,命名空间或全局,带或不带参数(包括 Array 对象),提供对遇到的任何错误的反馈(希望能捕获它们)。

The sample output shows how it works:示例输出显示了它的工作原理:

// calling a global function without parms
executeFunctionByName( 'a' );
  /* OUTPUT:
  global func passed:
  */

// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
  /* OUTPUT:
  global func passed:
  -> 123
  */

// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
  /* OUTPUT:
  namespace func passed:
  */

// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  */

// calling a namespaced function, with explicit context as separate arg, passing a string literal and array 
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  -> 7,is the man
  */

// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
  /* OUTPUT:
  global func passed:
  -> nsa
  */

// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
  /* OUTPUT:
  Uncaught n_s_a is not a function
  */

// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
  /* OUTPUT:
  Uncaught Snowden is not a function
  */

// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
  /* OUTPUT:
  Uncaught [object Object].a is not a function
  */

// calling no function
executeFunctionByName();
  /* OUTPUT:
  Uncaught function name not specified
  */

// calling by empty string
executeFunctionByName( '' );
  /* OUTPUT:
  Uncaught  is not a function
  */

// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
  /* OUTPUT:
  Uncaught [object Object].noSuchAgency is not a function
  */

If you want to call a function of an object instead of a global function with window["functionName"] .如果要使用window["functionName"]调用对象的函数而不是全局函数。 You can do it like;你可以这样做;

var myObject=new Object();
myObject["functionName"](arguments);

Example:例子:

var now=new Date();
now["getFullYear"]()

BE CAREFUL!!!当心!!!

One should try to avoid calling a function by string in JavaScript for two reasons:出于两个原因,应该尽量避免在 JavaScript 中通过字符串调用函数:

Reason 1: Some code obfuscators will wreck your code as they will change the function names, making the string invalid.原因 1:一些代码混淆器会破坏您的代码,因为它们会更改函数名称,使字符串无效。

Reason 2: It is much harder to maintain code that uses this methodology as it is much harder to locate usages of the methods called by a string.原因 2:维护使用这种方法的代码要困难得多,因为查找字符串调用的方法的用法要困难得多。

Here is my Es6 approach which enables you to call your function by it's name as string or it's function name and also enable you to pass different numbers of arguments to different types of functions:这是我的 Es6 方法,它使您可以通过名称作为字符串或函数名称来调用函数,还可以将不同数量的参数传递给不同类型的函数:

 function fnCall(fn, ...args) { let func = (typeof fn =="string")?window[fn]:fn; if (typeof func == "function") func(...args); else throw new Error(`${fn} is Not a function!`); } function example1(arg1){console.log(arg1)} function example2(arg1, arg2){console.log(arg1 + " and " + arg2)} function example3(){console.log("No arguments!")} fnCall("example1", "test_1"); fnCall("example2", "test_2", "test3"); fnCall(example3); fnCall("example4"); // should raise an error in console

Surprised to see no mention of setTimeout.惊讶地看到没有提到 setTimeout。

To run a function without arguments:要运行不带参数的函数:

var functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);

To run function with arguments:要运行带参数的函数:

var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");

To run deeply namespaced function:要运行深度命名空间函数:

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}
setTimeout("_very._deeply._defined._function(40,50)", 0);

I don't think you need complicated intermediate functions or eval or be dependent on global variables like window:我认为您不需要复杂的中间函数或 eval 或依赖于像 window 这样的全局变量:

function fun1(arg) {
  console.log(arg);
}

function fun2(arg) {
  console.log(arg);
}

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations.fun2("Hello World");

// You can use intermediate variables, if you like
let temp = "fun1";
operations[temp]("Hello World");

It will also work with imported functions:它也适用于导入的函数:

// mode.js
export function fun1(arg) {
  console.log(arg);
}

export function fun2(arg) {
  console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";

const operations = {
  fun1,
  fun2
};

operations["fun1"]("Hello World");
operations["fun2"]("Hello World");

Since it is using property access, it will survive minimization or obfuscation, contrary to some answers you will find here.由于它使用的是属性访问,因此它可以在最小化或混淆中幸存下来,这与您在此处找到的一些答案相反。

So, like others said, definitely the best option is:所以,就像其他人说的,绝对是最好的选择:

window['myfunction'](arguments)

And like Jason Bunting said , it won't work if the name of your function includes an object:就像Jason Bunting 所说的那样,如果您的函数名称包含一个对象,它将无法工作:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work

So here's my version of a function that will execute all functions by name (including an object or not):所以这是我的函数版本,它将按名称执行所有函数(包括或不包括对象):

 my = { code : { is : { nice : function(a, b){ alert(a + "," + b); } } } }; guy = function(){ alert('awesome'); } function executeFunctionByName(str, args) { var arr = str.split('.'); var fn = window[ arr[0] ]; for (var i = 1; i < arr.length; i++) { fn = fn[ arr[i] ]; } fn.apply(window, args); } executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']); executeFunctionByName('guy');

  let t0 = () => { alert('red0') }
  var t1 = () =>{ alert('red1') }
  var t2 = () =>{ alert('red2') }
  var t3 = () =>{ alert('red3') }
  var t4 = () =>{ alert('red4') }
  var t5 = () =>{ alert('red5') }
  var t6 = () =>{ alert('red6') }

  function getSelection(type) {
    var evalSelection = {
      'title0': t0,
      'title1': t1,
      'title2': t2,
      'title3': t3,
      'title4': t4,
      'title5': t5,
      'title6': t6,
      'default': function() {
        return 'Default';
      }
    };
    return (evalSelection[type] || evalSelection['default'])();
  }
  getSelection('title1');

A more OOP solution ...一个更加面向对象的解决方案......

One more detail on Jason and Alex's posts.关于 Jason 和 Alex 的帖子的更多细节。 I found it helpful to add a default value to context.我发现为上下文添加默认值很有帮助。 Just put context = context == undefined? window:context;只需放置context = context == undefined? window:context; context = context == undefined? window:context; at the beginning of the function.在函数的开头。 You can change window to whatever your preferred context is, and then you won't need to pass in the same variable each time you call this in your default context.您可以将window更改为您喜欢的任何上下文,然后每次在默认上下文中调用它时都不需要传入相同的变量。

要添加到 Jason Bunting 的答案中,如果您使用的是 nodejs 或其他东西(这也适用于 dom js),您可以使用this代替window (并记住:eval 是邪恶的

this['fun'+'ctionName']();

There's a very similar thing in my code.我的代码中有一个非常相似的东西。 I have a server-generated string which contains a function name which I need to pass as a callback for a 3rd party library.我有一个服务器生成的字符串,其中包含一个函数名称,我需要将其作为第 3 方库的回调传递。 So I have a code that takes the string and returns a "pointer" to the function, or null if it isn't found.所以我有一个代码,它接受字符串并返回一个指向函数的“指针”,如果找不到,则返回 null。

My solution was very similar to " Jason Bunting's very helpful function " * , although it doesn't auto-execute, and the context is always on the window.我的解决方案与“ Jason Bunting 的非常有用的功能*非常相似,尽管它不会自动执行,并且上下文始终在窗口上。 But this can be easily modified.但这可以很容易地修改。

Hopefully this will be helpful to someone.希望这会对某人有所帮助。

/**
 * Converts a string containing a function or object method name to a function pointer.
 * @param  string   func
 * @return function
 */
function getFuncFromString(func) {
    // if already a function, return
    if (typeof func === 'function') return func;

    // if string, try to find function or method of object (of "obj.func" format)
    if (typeof func === 'string') {
        if (!func.length) return null;
        var target = window;
        var func = func.split('.');
        while (func.length) {
            var ns = func.shift();
            if (typeof target[ns] === 'undefined') return null;
            target = target[ns];
        }
        if (typeof target === 'function') return target;
    }

    // return null if could not parse
    return null;
}

There too some very helpful way.还有一些非常有用的方法。

http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx

var arrayMaker = {  
    someProperty: 'some value here',  
    make: function (arg1, arg2) {  
        return [ this, arg1, arg2 ];  
    },
    execute: function_name
};

I can't resist mentioning another trick, which helps if you have an unknown number of arguments that are also being passed as part of the string containing the function name.我忍不住要提到另一个技巧,如果您有未知数量的参数也作为包含函数名称的字符串的一部分传递,这会很有帮助 For example:例如:

var annoyingstring = 'call_my_func(123, true, "blah")';

If your Javascript is running on a HTML page, all you need is an invisible link;如果您的 Javascript 运行在 HTML 页面上,您只需要一个不可见的链接; you can pass a string into the onclick attribute, and the call the click method.您可以将字符串传递给onclick属性,然后调用click方法。

<a href="#" id="link_secret"><!-- invisible --></a>

$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();

Or create the <a> element at runtime.或者在运行时创建<a>元素。

Easiest way is to access it like has element最简单的方法是像拥有元素一样访问它

window.ClientSideValidations.forms.location_form

is same as

window.ClientSideValidations.forms['location_form']

People keep saying that eval is dangerous and evil because it can run any arbitrary code.人们一直说eval是危险和邪恶的,因为它可以运行任意代码。 However, if you use eval with a whitelisting approach, assuming you know all the possible function names that may need to be run in advance, then eval is no longer a security concern because the input is no longer arbitrary .但是,如果您将 eval 与白名单方法一起使用,假设您知道可能需要提前运行的所有可能的函数名称,那么 eval 不再是一个安全问题,因为输入不再是任意的 Whitelisting is a good and frequent security pattern.白名单是一种良好且频繁的安全模式。 Here's an example:下面是一个例子:

 function runDynamicFn(fnName, ...args) { // can also be fed from a tightly controlled config const allowedFnNames = ['fn1', 'ns1.ns2.fn3', 'ns4.fn4']; return allowedFnNames.includes(fnName) ? eval(fnName)(...args) : undefined; } // test function: function fn1(a) { console.log('fn1 called with', a) } runDynamicFn('alert("got you!")') runDynamicFn('fn1', 'foo')

Here's a bit robust and reusable solution I ended up implementing for one of my projects.这是我最终为我的一个项目实施的一个有点强大且可重用的解决方案。

A FunctionExecutor Constructor Function FunctionExecutor 构造函数

Usage:用法:

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

Obviously in the project the adding of all the functions that required to be called by name was done by a loop.显然,在项目中,所有需要按名称调用的函数的添加都是通过循环完成的。

The function Executor:函数执行器:

function FunctionExecutor() {
  this.functions = {};

  this.addFunction = function (fn) {
    let fnName = fn.name;
    this.functions[fnName] = fn;
  }

  this.execute = function execute(fnName, ...args) {
    if (fnName in this.functions && typeof this.functions[fnName] === "function") {
      return this.functions[fnName](...args);
    }
    else {
      console.log("could not find " + fnName + " function");
    }
  }

  this.logFunctions = function () {
    console.log(this.functions);
  }
}

Example Usage:示例用法:

function two() {
  console.log("two"); 
}

function three() {
  console.log("three");
}

let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)

executor.execute("one");
executor.execute("three");

This is working for me:这对我有用:

var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);

I hope this works.我希望这有效。

Without using eval('function()') you could to create a new function using new Function(strName) . 在不使用eval('function()')您可以使用new Function(strName)创建一个新函数。 The below code was tested using FF, Chrome, IE. 以下代码已使用FF,Chrome,IE进行了测试。

<html>
<body>
<button onclick="test()">Try it</button>
</body>
</html>
<script type="text/javascript">

  function test() {
    try {    
        var fnName = "myFunction()";
        var fn = new Function(fnName);
        fn();
      } catch (err) {
        console.log("error:"+err.message);
      }
  }

  function myFunction() {
    console.log('Executing myFunction()');
  }

</script>
use this

function executeFunctionByName(functionName, context /*, args */) {
      var args = [].slice.call(arguments).splice(2);
      var namespaces = functionName.split(".");
      var func = namespaces.pop();
      for(var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
      }
      return context[func].apply(context, args);
    }

Look basic:看基本:

var namefunction = 'jspure'; // String

function jspure(msg1 = '', msg2 = '') { 
  console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument

// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple

Exist other type function is class and look example nils petersohn存在其他类型的函数是class并查看示例nils petersohn

Thanks for the very helpful answer.感谢您提供非常有帮助的答案。 I'm using Jason Bunting's function in my projects.我在我的项目中使用Jason Bunting 的功能

I extended it to use it with an optional timeout, because the normal way to set a timeout wont work.我将它扩展为使用可选超时,因为设置超时的正常方法不起作用。 See abhishekisnot's question查看abhishekisnot 的问题

 function executeFunctionByName(functionName, context, timeout /*, args */ ) { var args = Array.prototype.slice.call(arguments, 3); var namespaces = functionName.split("."); var func = namespaces.pop(); for (var i = 0; i < namespaces.length; i++) { context = context[namespaces[i]]; } var timeoutID = setTimeout( function(){ context[func].apply(context, args)}, timeout ); return timeoutID; } var _very = { _deeply: { _defined: { _function: function(num1, num2) { console.log("Execution _very _deeply _defined _function : ", num1, num2); } } } } console.log('now wait') executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );

There are several executeByName functions here which works fine, unless name contains square brackets - issue I ran into - as I have dynamically generated names.这里有几个executeByName函数可以正常工作,除非名称包含方括号- 我遇到的问题 - 因为我有动态生成的名称。 So above functions will fail on names like所以上面的函数会在名称上失败,比如

app.widget['872LfCHc']['toggleFolders']

As a remedy, I've made function to take this into account too, maybe someone will find it usefull:作为一种补救措施,我也制定了功能来考虑这一点,也许有人会发现它很有用:

Generated from CoffeeScript:从 CoffeeScript 生成:

var executeByName = function(name, context) {
  var args, func, i, j, k, len, len1, n, normalizedName, ns;
  if (context == null) {
    context = window;
  }
  args = Array.prototype.slice.call(arguments, 2);
  normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.');
  ns = normalizedName.split(".");
  func = context;
  for (i = j = 0, len = ns.length; j < len; i = ++j) {
    n = ns[i];
    func = func[n];
  }
  ns.pop();
  for (i = k = 0, len1 = ns.length; k < len1; i = ++k) {
    n = ns[i];
    context = context[n];
  }
  if (typeof func !== 'function') {
    throw new TypeError('Cannot execute function ' + name);
  }
  return func.apply(context, args);
}

For better readability check also CoffeeScript version:为了更好的可读性,还检查 CoffeeScript 版本:

executeByName = (name, context = window) ->
    args = Array.prototype.slice.call(arguments, 2)
    normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.')
    ns = normalizedName.split "."
    func = context
    for n, i in ns
        func = func[n]

    ns.pop()
    for n, i in ns
        context = context[n];
    if typeof func != 'function'
        throw new TypeError 'Cannot execute function ' + name
    func.apply(context, args)

You can call javascript function within the eval("functionname as string") either.您也可以在eval("functionname as string")调用 javascript 函数。 Like below: (eval is pure javascript function)如下所示:(eval 是纯 javascript 函数)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

Working example: https://jsfiddle.net/suatatan/24ms0fna/4/工作示例: https : //jsfiddle.net/suatatan/24ms0fna/4/

I have the name of a function in JavaScript as a string.我有一个JavaScript函数的名称作为字符串。 How do I convert that into a function pointer so I can call it later?如何将其转换为函数指针,以便以后可以调用?

Depending on the circumstances, I may need to pass various arguments into the method too.根据具体情况,我可能还需要将各种参数传递给该方法。

Some of the functions may take the form of namespace.namespace.function(args[...]) .一些功能可能采用namespace.namespace.function(args[...])

Since eval() is evil, and new Function() is not the most efficient way to achieve this, here is a quick JS function that returns the function from its name in string.由于eval()是邪恶的,而new Function()不是实现此目的的最有效方法,这里是一个快速的 JS function,它从字符串中的名称返回 function。

  • Works for namespace'd functions适用于命名空间的功能
  • Fallbacks to null-function in case of null/undefined string在空/未定义字符串的情况下回退到空函数
  • Fallbacks to null-function if function not found如果找不到 function,则回退到空函数

    function convertStringtoFunction(functionName){

        var nullFunc = function(){}; // Fallback Null-Function
        var ret = window; // Top level namespace

        // If null/undefined string, then return a Null-Function
        if(functionName==null) return nullFunc;

        // Convert string to function name
        functionName.split('.').forEach(function(key){ ret = ret[key]; });

        // If function name is not available, then return a Null-Function else the actual function
        return (ret==null ? nullFunc : ret);

    }

Usage:用法:


    convertStringtoFunction("level1.midLevel.myFunction")(arg1, arg2, ...);

You may place your functions names in an Array object and then call the array key respective to each function to execute it, DEMO :您可以将您的函数名称放在数组 object 中,然后分别调用每个 function 的数组键来执行它, DEMO

function captchaTest(msg){
    let x = Math.floor(Math.random()*(21-1)) +1;
    let y = Math.floor(Math.random()*(11-1)) +1;
    let sum = function(){
        return x+y;
    }
    let sub = function(){
        if (y > x){
            let m = y;
            y = x;
            x = m;
            console.log(x,y,m,'--')
        }
        return x-y;
    }
    let mul = function(){
        return x*y;
    } 
    let OParr = [sum(), sub(), mul()]; 
    let OP = Math.floor(Math.random()*OParr.length);      
    let s = OParr[OP]; //!!! HERE !!! is the call as array element
    switch(OP){
        case 0:
            opra = '+';
            break;
        case 1:
            opra = '━';
            break;
        default:
            opra = '✖';
    }
    let msg2 = 'Answer the following question to continue:'
    let p = prompt(msg+' '+msg2+'\n'+'What is the result of '+x+opra+y+' ?','')
    console.log(s,p,OP)
    if (s == p){
        alert ('Wow, Correct Answer!')
        return true;
    }
    else{
        alert('Sorry, the answer is not correct!')
        return false;
    }
}
  const myFnCollection = {
    myFnStringName: function(args) {}
  };

  let fn = 'myFnStringName';

  // 1. Recommended
  if (typeof window[fn] === 'function') {
    window[fn](args);
  }

  // 2. Recommended
  if (typeof myFnCollection[fn] === 'function') {
    myFnCollection[fn](args);
  }

  // 3. Eval is evil ;)
  if (typeof eval(fn) === 'function') {
    eval(fn)(args);
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我将其名称作为字符串时执行 JavaScript 函数 - 不工作 - Execute a JavaScript function when I have its name as a string - Not working 如何执行 JavaScript Function 当我将其名称作为字符串时(使用具有重载参数的参数) - How to execute a JavaScript Function When I have its name as a string (with parameters that have an overload argument) 当我将其名称作为字符串时,如何执行私有JavaScript函数 - How to execute a private JavaScript function when I have its name as a string 当其名称作为字符串传递给函数时,如何执行JavaScript函数? - How to execute a JavaScript function when its name is passed as a string in function? 当我不带参数动态将其名称作为字符串发送时,如何执行javascript函数 - how to execute javascript function when i send its name as string dynamically with out parameters 如何在Edge中执行名称为字符串的JavaScript函数 - How to execute a JavaScript function having its name as a string in Edge 当我将其名称作为字符串时如何执行Angular控制器方法 - How to execute a Angular controller method when I have its name as a string 当我有 function 名称时执行 function 的正确方法 - Correct way to execute a function when I have function name 如何从HTML元素执行javascript函数并发送该元素名称,而无需专门使用其名称? - How do I execute a javascript function from an HTML element and send that elements name without use its name specifically? 如果您在javascript中有其名称的字符串,如何访问该类? - How to access a class if you have a string of its name in javascript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM