【问题标题】:How to execute a JavaScript function when I have its name as a string当我将其名称作为字符串时如何执行 JavaScript 函数
【发布时间】:2010-09-26 11:08:47
【问题描述】:

我在 JavaScript 中有一个函数的名称作为字符串。如何将其转换为函数指针,以便稍后调用?

根据情况,我可能还需要将各种参数传递给方法。

部分函数可能采用namespace.namespace.function(args[...])的形式。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    不要使用eval,除非您绝对肯定别无选择。

    如前所述,使用这样的方法是最好的方法:

    window["functionName"](arguments);
    

    但是,这不适用于命名空间的函数:

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

    你会这样做:

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

    为了使这更容易并提供一些灵活性,这里有一个方便的功能:

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

    你可以这样称呼它:

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

    注意,你可以在任何你想要的上下文中传递,所以这和上面的一样:

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

    【讨论】:

    • 你知道你不需要整个“func”结构吗?单独使用“context.apply”就可以了
    • 当然,我知道 - 但我编写函数的方式为那些阅读它的人提供了一些清晰性,可能无法完全理解正在发生的事情。我写了这个函数,意识到阅读它的人可能需要一些帮助。我会提供一个替代方案,因为你问...
    • 从头开始 - 代码足够清晰,知道的人都知道。如果您像我一样,并且知道自己在做什么,那么如果您使用此代码,则可以自己进行此类更改。 Stack Overflow 是用来教育别人的,我觉得我的代码对于新手来说更容易理解。不过谢谢!
    • 是否存在 window["funcName"] 会返回 undefined 的情况?这就是我目前遇到的问题。调用代码和函数定义在两个单独的 js 文件中。我尝试将它们添加到同一个文件中,但没有任何区别。
    • 我觉得这里有问题。当您调用My.Namespace.functionName() 时,this 将引用My.Namespace 对象。但是当你打电话给executeFunctionByName("My.Namespace.functionName", window) 时,没有办法让this 指代相同的东西。也许它应该使用最后一个命名空间作为范围,或者如果没有命名空间,则使用window。或者您可以允许用户将范围指定为参数。
    【解决方案2】:

    只是想我会发布一个稍微改动过的 Jason Bunting's very helpful function 版本。

    首先,我通过向 slice() 提供第二个参数来简化第一条语句。原始版本在除 IE 之外的所有浏览器中都能正常运行。

    其次,我在return语句中将this替换为context;否则,当目标函数被执行时,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);
    }
    

    【讨论】:

    • 没有检查“functionName”是否真的存在?
    • 我认为 Mac 的回答被低估了。我不是专家,但它似乎经过深思熟虑且功能强大。
    【解决方案3】:

    另一个问题的答案向您展示了如何做到这一点:Javascript equivalent of Python's locals()?

    基本上可以说

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

    或者正如许多其他人建议的那样,您可以使用 eval:

    eval(fname)(arg1, arg2);
    

    虽然这非常不安全,除非你完全确定你在评估什么。

    【讨论】:

    • 第一种形式更可取
    • 只有在万不得已时才使用 eval。
    • 它是......但它可以与这样的函数一起使用吗:x.y.z(args)?
    • @keiron:是的。请看下面我的回答
    【解决方案4】:

    我认为一种优雅的方法是在哈希对象中定义你的函数。然后,您可以使用字符串从哈希中引用这些函数。例如

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

    然后你可以调用:

    customObject['customFunction'](param);
    

    其中 customFunction 将是一个与您的对象中定义的函数匹配的字符串。

    更新

    似乎这个答案对许多其他编码人员有帮助,所以这里有一个更新版本。

    在 ES6 中,您还可以使用 Computed Property Names,这样可以避免使用魔法字符串。

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

    【讨论】:

    • @ibsenv,感谢您的评论,以帮助我将此回复确定为最佳回复。我创建了一个函数对象数组,然后用它来创建一个 deferred.promises 数组。我在下面放了一些示例代码。 (我不想创建新的回复并借用鲁本的回复。)
    • function getMyData(arrayOfObjectsWithIds) { var functionArray = arrayOfObjectsWithIds.map( function (value) { return {myGetDataFunction: MyService.getMyData(value.id)}; }) var promises = functionArray.map( function (getDataFunction) { var deferred =$q.defer(); getDataFunction.myGetDataFunction.success( function(data) { deferred.resolve(data) }).error( function (error) { deferred.reject(); });返回 deferred.promise; }); $q.all(promises).then( function (dataArray) { //do stuff }) };
    • 这很好用我只添加下划线/lodash 来验证它是否是一个函数。然后运行
    【解决方案5】:

    你不能这样做吗:

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

    您也可以使用此方法执行任何其他 JavaScript。

    【讨论】:

    • 在函数中传递偶数参数时有效
    • 函数返回呢?
    • 这和eval("My.Namespace.functionName()");有什么不同?
    • @PeterDenev 只需将第一行更改为var codeToExecute = "return My.Namespace.functionName()";
    • @developerbmw,这里是答案stackoverflow.com/questions/4599857/…
    【解决方案6】:

    使用 ES6,您可以通过名称访问类方法:

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

    输出将是:

    1
    2
    

    【讨论】:

    • Best javascript PURE ...上帝..删除类不起作用,但没关系。谢谢!
    • 这是我一直在寻找的东西。谢谢!
    • ES2015 与这里无关。您可以使用纯对象或通过Object.create() 进行原型委托来实现相同的目标。 const myObj = { method1() { console.log('1') }, method2() { console.log('2') } } myObj['method1'](); // 1 myObj['method2'](); // 2
    • 这是金子!!!我很惊讶我以前从未想过这一点。不错!!!
    • 我也认为这是实现我们目标的最佳方式。
    【解决方案7】:

    两件事:

    • 避免 eval,它非常危险而且速度很慢

    • 其次,您的函数存在于何处并不重要,“全局”-ness 是无关紧要的。 x.y.foo() 可以通过x.y['foo']()x['y']['foo']() 甚至window['x']['y']['foo']() 启用。你可以像这样无限地链接。

    【讨论】:

    • 但是你不能用 window['x.y.z']() 来调用 x.y.z()
    【解决方案8】:

    所有答案都假设可以通过全局范围(窗口)访问函数。但是,OP 没有做出这个假设。

    如果函数位于本地范围内(也称为闭包)并且没有被其他本地对象引用,那么运气不好:您必须使用 eval()AFAIK,请参阅 dynamically call local function in javascript

    【讨论】:

    • Dude(或 dudette),非常感谢您指出这一点!我以为我要疯了一秒钟。
    • 如果它在本地对象中你可以这样做:localobject['function_name'](),和window['function_name']()一样
    【解决方案9】:

    根据您所在的位置,您还可以使用:

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

    或者,在nodejs中

    global["funcname"]()
    

    【讨论】:

    • 感谢这个答案,可以function callObjectMethod(obj,meth){ return (_v) =&gt; { obj[meth](_v) } }。对我来说,调用一些带有来自外部服务回调的参数的对象方法很有用。希望这对其他人有帮助。
    【解决方案10】:

    您只需要将字符串转换为window[&lt;method name&gt;] 的指针。 示例:

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

    现在你可以像使用指针一样使用它了。

    【讨论】:

    • 这似乎是一种更安全的方式。
    【解决方案11】:

    这是我对 Jason Bunting / Alex Nazarov 出色答案的贡献,其中包括 Crashalot 要求的错误检查。

    鉴于这个(人为的)序言:

    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(){};
    

    然后是下面的函数:

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

    将允许您按存储在字符串中的名称调用 javascript 函数,无论是命名空间还是全局,带或不带参数(包括 Array 对象),就遇到的任何错误提供反馈(希望能够捕获它们)。

    示例输出显示了它是如何工作的:

    // 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
      */
    

    【讨论】:

    • 不知道......这是一个非常好的努力,很清楚。但对我来说听起来“太宽泛”了......
    • 嗯? SO是一个问答/教学平台。我很乐意提供我能想到的所有例子,希望能传达启发。对我来说,这就是重点
    • 如果您仍然在评估 functionName,为什么不直接使用它呢?
    • 这对我不起作用。我有一个命名空间函数 a.b.c.d,其中 d 是函数名。调用 executeFunctionByName("abcd", window) 在检查 if( typeof context[ functionName ] !== 'function' ) 的线上失败,因为上下文 - 窗口 - 已定义,是一个对象和一个数组,但 window['abcd'] 不存在,因为被标识为已接受答案中的问题:window["My.Namespace.functionName"](arguments); // fail
    【解决方案12】:

    如果你想用window["functionName"]调用一个对象的函数而不是一个全局函数。你可以这样做;

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

    例子:

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

    【讨论】:

      【解决方案13】:

      小心!!!

      人们应该尽量避免在 JavaScript 中通过字符串调用函数,原因有二:

      原因 1:某些代码混淆器会破坏您的代码,因为它们会更改函数名称,使字符串无效。

      原因 2:维护使用这种方法的代码要困难得多,因为要找到字符串调用的方法的用法要困难得多。

      【讨论】:

        【解决方案14】:

        这是我的 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

        【讨论】:

          【解决方案15】:

          惊讶地发现没有提到 setTimeout。

          要运行不带参数的函数:

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

          使用参数运行函数:

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

          运行深度命名空间函数:

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

          【讨论】:

          • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post
          • 请添加一个示例,说明您将如何使用一些参数调用runMe
          • @lexicore 我在审查队列中投了 deletion 票,因为它没有清楚地 为这个问题提供实质性答案,而且几乎没有自己的价值。
          • 这个方法有潜在的巨大缺陷,因为它把执行放到渲染结束队列,从而使这个调用异步
          • 我喜欢这个答案,它似乎符合我的要求。
          【解决方案16】:

          我认为您不需要复杂的中间函数或 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");
          

          它也适用于导入的函数:

          // 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");
          

          由于它使用属性访问,因此它可以在最小化或混淆中幸存下来,这与您在此处找到的一些答案相反。

          【讨论】:

            【解决方案17】:

            所以,正如其他人所说,绝对是最好的选择:

            window['myfunction'](arguments)
            

            Jason Bunting said 一样,如果你的函数名包含一个对象,它将不起作用:

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

            所以这是我的函数版本,它将按名称执行所有函数(包括或不包括对象):

            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');

            【讨论】:

              【解决方案18】:
                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');
              

              更多的 OOP 解决方案 ...

              【讨论】:

                【解决方案19】:

                关于 Jason 和 Alex 帖子的更多详细信息。我发现向上下文添加默认值很有帮助。只需将context = context == undefined? window:context; 放在函数的开头即可。您可以将window 更改为您喜欢的任何上下文,然后每次在默认上下文中调用它时都不需要传递相同的变量。

                【讨论】:

                  【解决方案20】:

                  添加到 Jason Bunting 的答案中,如果您使用的是 nodejs 或其他东西(这也适用于 dom js),您可以使用 this 而不是 window(请记住:eval 是 evil

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

                  【讨论】:

                    【解决方案21】:

                    我的代码中有一个非常相似的东西。 我有一个服务器生成的字符串,其中包含一个函数名称,我需要将其作为第 3 方库的回调传递。所以我有一个代码,它接受字符串并返回一个指向函数的“指针”,如果没有找到,则返回 null。

                    我的解决方案与“Jason Bunting's very helpful function* 非常相似,尽管它不会自动执行,并且上下文始终在窗口中。但这很容易修改。

                    希望这对某人有所帮助。

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

                    【讨论】:

                      【解决方案22】:

                      这是我最终为我的一个项目实施的一个强大且可重复使用的解决方案。

                      一个 FunctionExecutor 构造函数

                      用法:

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

                      显然在项目中需要通过名称调用的所有函数的添加都是通过循环完成的。

                      函数Exec​​utor:

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

                      示例用法:

                      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");
                      

                      【讨论】:

                        【解决方案23】:

                        还有一些非常有用的方法。

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

                        【讨论】:

                          【解决方案24】:

                          我忍不住要提到另一个技巧,如果您有未知数量的参数也作为包含函数名称的字符串的一部分传递,它会有所帮助。例如:

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

                          如果您的 Javascript 在 HTML 页面上运行,您所需要的只是一个不可见的链接;您可以将字符串传递给onclick 属性,然后调用click 方法。

                          &lt;a href="#" id="link_secret"&gt;&lt;!-- invisible --&gt;&lt;/a&gt;

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

                          或者在运行时创建&lt;a&gt; 元素。

                          【讨论】:

                          • 创造性的解决方案,但这不适用于对象或数组类型的参数。
                          • 这是在后台使用 eval ......而且真的在拐弯抹角地做到这一点
                          【解决方案25】:

                          最简单的方法是像拥有元素一样访问它

                          window.ClientSideValidations.forms.location_form
                          

                          相同
                          window.ClientSideValidations.forms['location_form']
                          

                          【讨论】:

                            【解决方案26】:

                            人们一直说eval 既危险又邪恶,因为它可以运行任意代码。但是,如果您将 eval 与 whitelisting 方法一起使用,假设您知道所有可能需要提前运行的函数名称,则 eval 不再是安全问题,因为输入是 不再随意。白名单是一种良好且常见的安全模式。这是一个例子:

                            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')

                            【讨论】:

                            • 在我看来这仍然是一个糟糕的实现;最好映射功能:let allowedFns = new Map(); allowedFns.set('fn1', fn1); allowedFns.set('ns1.ns2.fn3', ns1.ns2.fn3); ...。如果eval的使用是安全的,那么不用eval也可以解决问题:-P
                            • 如果你知道所有的函数名,为什么不直接用函数创建一个数组呢?
                            【解决方案27】:

                            看起来很基本:

                            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
                            

                            现有的其他类型函数是class,看例子nils petersohn

                            【讨论】:

                              【解决方案28】:

                              感谢您提供非常有帮助的答案。我在我的项目中使用Jason Bunting's function

                              我将它扩展为使用可选超时,因为设置超时的正常方法行不通。见abhishekisnot's question

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

                              【讨论】:

                                【解决方案29】:

                                这里有几个 executeByName 函数可以正常工作,除非名称包含 方括号 - 我遇到的问题 - 因为我有动态生成的名称。所以上面的函数会在像

                                这样的名字上失败

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

                                作为一种补救措施,我也考虑了这一点,也许有人会觉得它有用:

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

                                为了更好的可读性,还要检查 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)
                                

                                【讨论】:

                                  【解决方案30】:

                                  您也可以在eval("functionname as string") 中调用javascript 函数。如下:(eval是纯javascript函数)

                                  function testfunc(){
                                      return "hello world";
                                  }
                                  
                                  $( document ).ready(function() {
                                  
                                       $("div").html(eval("testfunc"));
                                  });
                                  

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

                                  【讨论】:

                                  • 这很好用而且很简单
                                  • 而且真的很慢。
                                  猜你喜欢
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2018-12-03
                                  • 1970-01-01
                                  • 2018-08-22
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多