【问题标题】:Is there a way to create a function from a string with javascript?有没有办法用javascript从字符串创建函数?
【发布时间】:2011-11-30 19:02:50
【问题描述】:

例如;

var s = "function test(){
  alert(1);
}";

var fnc = aMethod(s);

如果这是字符串,我想要一个名为 fnc 的函数。并且fnc(); 会弹出警报屏幕。

eval("alert(1);") 没有解决我的问题。

【问题讨论】:

    标签: javascript string function


    【解决方案1】:

    我为从字符串创建函数的 4 种不同方法添加了 jsperf 测试:

    • 在函数类中使用正则表达式

      var func = "function (a, b) { return a + b; }".parseFunction();

    • 使用带有“return”的函数类

      var func = new Function("return " + "function (a, b) { return a + b; }")();

    • 使用官方的 Function 构造函数

      var func = new Function("a", "b", "return a + b;");

    • 使用评估

      eval("var func = function (a, b) { return a + b; };");

    http://jsben.ch/D2xTG

    2 个结果样本:

    【讨论】:

    • @KthProg 冷静下来;)。并不总是很糟糕,像这种情况,jsperf 目前处于 down 状态,幸运的是,当我收到 Bulk 的评论时,我在它 down 之前添加了结果截图。
    • @KthProg 仅供参考,这是审核系统生成的预设回复 :) 它会在队列中弹出,我们会检查预先确定的问题,此评论旨在解决其中一个问题。这不是一个硬性规定,你会注意到评论是以建议而不是命令的形式出现的。
    【解决方案2】:

    使用 new Function() 并在内部返回并立即执行。

    var s = `function test(){
      alert(1);
    }`;
    
    var new_fn = new Function("return " + s)()
    console.log(new_fn)
    new_fn()

    【讨论】:

      【解决方案3】:

      一个动态参数的例子:

      let args = {a:1, b:2}
        , fnString = 'return a + b;';
      
      let fn = Function.apply(Function, Object.keys(args).concat(fnString));
      
      let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))
      

      【讨论】:

      • 谢谢。很有趣
      【解决方案4】:

      这种技术最终可能等同于 eval 方法,但我想添加它,因为它可能对某些人有用。

      var newCode = document.createElement("script");
      
      newCode.text = "function newFun( a, b ) { return a + b; }";
      
      document.body.appendChild( newCode );
      

      这在功能上类似于将这个

      ...
      
      <script type="text/javascript">
      function newFun( a, b ) { return a + b; }
      </script>
      
      </body>
      </html>
      

      【讨论】:

        【解决方案5】:

        是的,使用Function 是一个很好的解决方案,但我们可以更进一步,准备通用解析器来解析字符串并将其转换为真正的 JavaScript 函数...

        if (typeof String.prototype.parseFunction != 'function') {
            String.prototype.parseFunction = function () {
                var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
                var match = funcReg.exec(this.replace(/\n/g, ' '));
        
                if(match) {
                    return new Function(match[1].split(','), match[2]);
                }
        
                return null;
            };
        }
        

        使用示例:

        var func = 'function (a, b) { return a + b; }'.parseFunction();
        alert(func(3,4));
        
        func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
        func();
        

        here 是 jsfiddle

        【讨论】:

        • 您好,请支持此方法的箭头功能支持吗?
        • 我在 typecirpt 中收到此错误“类型 'String' 上不存在属性 'parseFunction'。”
        【解决方案6】:

        JavaScript 中的动态函数名称

        使用Function

        var name = "foo";
        // Implement it
        var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
        // Test it
        func();
        // Next is TRUE
        func.name === 'foo'
        

        来源:http://marcosc.com/2012/03/dynamic-function-names-in-javascript/

        使用eval

        var name = "foo";
        // Implement it
        eval("function " + name + "() { alert('Foo'); };");
        // Test it
        foo();
        // Next is TRUE
        foo.name === 'foo'
        

        使用sjsClass

        https://github.com/reduardo7/sjsClass

        示例

        Class.extend('newClassName', {
            __constructor: function() {
                // ...
            }
        });
        
        var x = new newClassName();
        // Next is TRUE
        newClassName.name === 'newClassName'
        

        【讨论】:

          【解决方案7】:

          从字符串创建函数的更好方法是使用Function

          var fn = Function("alert('hello there')");
          fn();
          

          这具有优点/缺点,即当前范围内的变量(如果不是全局变量)不适用于新构造的函数。

          也可以传递参数:

          var addition = Function("a", "b", "return a + b;");
          alert(addition(5, 3)); // shows '8'
          

          【讨论】:

          • 同意,Function 不会污染本地范围,这就是为什么eval 使引擎的优化如此困难......以 OP 为例,我会:var fnc = Function('return '+s)();
          • 我认为这可能应该是公认的答案。它比 eval() 安全得多。
          • 你,我的朋友,应该得到很多支持。这具有创建可以分配给事件等的函数对象的优点。例如: element.onclick = Function("alert('test');");
          • @RyanGriggs 在您的情况下,您不需要“eval”功能,因此最好写为element.onclick = function() { alert("test"); }
          • 你在我的例子中是正确的。但是,如果您想分配存储在字符串中的任意函数,那么您的方法是完美的。这就是我真正想要做的。我有多个函数存储在字符串变量中,并希望将一个函数分配给 onclick 操作。
          【解决方案8】:

          你已经很接近了。

          //Create string representation of function
          var s = "function test(){  alert(1); }";
          
          //"Register" the function
          eval(s);
          
          //Call the function
          test();
          

          这里是a working fiddle

          【讨论】:

          • 我知道该函数已声明,但无法猜测调用函数名称。非常感谢。
          • 强制性eval 对未来搜索者的警告:eval 可以为黑客打开漏洞:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 但如果你知道它的危险并且可以避免它们,那么这是一个很好的简单方法来创建一个字符串中的函数
          • 如果你没有函数的名称,因为它来自数据库记录?
          猜你喜欢
          • 2017-08-17
          • 1970-01-01
          • 2014-08-23
          • 1970-01-01
          • 2021-10-25
          • 1970-01-01
          • 2012-05-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多