【问题标题】:Calling dynamic function with dynamic number of parameters [duplicate]使用动态数量的参数调用动态函数[重复]
【发布时间】:2010-10-15 04:08:05
【问题描述】:

我正在寻找一个技巧。我知道如何在 JavaScript 中调用动态的任意函数,传递特定的参数,如下所示:

function mainfunc(func, par1, par2){
    window[func](par1, par2);
}

function calledfunc(par1, par2){
    // Do stuff here
}

mainfunc('calledfunc', 'hello', 'bye');

我知道如何使用mainfunc 中的arguments 集合传递可选的、无限制的参数,但是,我不知道如何将任意数量的参数发送到mainfunc 以动态发送到calledfunc ;我怎样才能完成这样的事情,但可以使用任意数量的可选参数(不使用那个丑陋的ifelse)?

function mainfunc(func){
    if(arguments.length == 3)
        window[func](arguments[1], arguments[2]);
    else if(arguments.length == 4)
        window[func](arguments[1], arguments[2], arguments[3]);
    else if(arguments.length == 5)
        window[func](arguments[1], arguments[2], arguments[3], arguments[4]);
}

function calledfunc1(par1, par2){
    // Do stuff here
}

function calledfunc2(par1, par2, par3){
    // Do stuff here
}

mainfunc('calledfunc1', 'hello', 'bye');
mainfunc('calledfunc2', 'hello', 'bye', 'goodbye');

【问题讨论】:

标签: javascript function


【解决方案1】:

使用函数的apply方法:-

function mainfunc (func){
    window[func].apply(null, Array.prototype.slice.call(arguments, 1));
} 

编辑:在我看来,稍微调整一下会更有用:-

function mainfunc (func){
    this[func].apply(this, Array.prototype.slice.call(arguments, 1));
} 

这将在浏览器之外工作(this 默认为全局空间)。在 mainfunc 上使用 call 也可以:-

function target(a) {
    alert(a)
}

var o = {
    suffix: " World",
    target: function(s) { alert(s + this.suffix); }
};

mainfunc("target", "Hello");

mainfunc.call(o, "target", "Hello");

【讨论】:

  • 这是最合适的解决方案,但在参数中它会包含函数的名称(arguments[0]='func')。我可以使用除第一个参数之外的所有参数生成另一个数组,然后使用这个新数组,但是,还有其他不使用其他数组的解决方案吗?
  • ARemesal,请参阅我的解决方案答案(使用第一个参数作为函数名)
  • @ARemesal:糟糕,是的,忘记从参数中分割出 func 参数。查看我的编辑。
  • 是的 AnthonyWJones,它相当于 JimmyP 的解决方案。感谢您的解决方案,我发现了一些很棒的技巧:)
【解决方案2】:

您的代码仅适用于全局函数,即。 window 对象的成员。要将其与任意函数一起使用,请将函数本身而不是其名称作为字符串传递:

function dispatch(fn, args) {
    fn = (typeof fn == "function") ? fn : window[fn];  // Allow fn to be a function object or the name of a global function
    return fn.apply(this, args || []);  // args is optional, use an empty array by default
}

function f1() {}

function f2() {
    var f = function() {};
    dispatch(f, [1, 2, 3]);
}

dispatch(f1, ["foobar"]);
dispatch("f1", ["foobar"]);

f2();  // calls inner-function "f" in "f2"
dispatch("f", [1, 2, 3]);  // doesn't work since "f" is local in "f2"

【讨论】:

  • 这行得通,但你应该注意这不是所要求的
【解决方案3】:

你可以使用.apply()

你需要指定一个this...我猜你可以在mainfunc中使用this

function mainfunc (func)
{
    var args = new Array();
    for (var i = 1; i < arguments.length; i++)
        args.push(arguments[i]);

    window[func].apply(this, args);
}

【讨论】:

  • 您不需要将“参数”转换为 REAL 数组。这有什么意义?没有这一步它就可以完美地工作......
  • 如果你想省略第一个参数,它是函数的名称,则不是。
  • 那为什么不直接使用'shift'呢? (见我的回答)
  • 我没有使用 shift,因为我认为 [].xxx.call 在 IE 中不起作用,但我现在无法重现错误。
【解决方案4】:

这是你需要的:

function mainfunc (){
    window[Array.prototype.shift.call(arguments)].apply(null, arguments);
}

第一个参数用作函数名,其余的所有参数都用作被调用函数的参数...

我们可以使用shift 方法返回并删除参数数组中的第一个值。请注意,我们从 Array 原型中调用它,因为严格来说,“arguments”不是真正的数组,因此不会像常规数组那样继承 shift 方法。


你也可以这样调用 shift 方法:

[].shift.call(arguments);

【讨论】:

  • 非常感谢 JimmyP,您的解决方案(在编辑后)与 AnthonyWJones 的解决方案等效,您给了我关于使用 Array.prototype 和 [] 的重要提示和解释。
  • 奇怪,我确定我试过这个并且在 IE 中遇到了错误
【解决方案5】:

最简单的方法可能是:

var func='myDynamicFunction_'+myHandler;
var arg1 = 100, arg2 = 'abc';

window[func].apply(null,[arg1, arg2]);

假设,目标函数已经附加到一个“窗口”对象。

【讨论】:

    【解决方案6】:

    如果你想传递一些其他的“参数”,你必须一起创建所有参数的数组,即像这样:

    var Log = {
        log: function() {
            var args = ['myarg here'];
            for(i=0; i<arguments.length; i++) args = args.concat(arguments[i]);
            console.log.apply(this, args);
        }
    }
    

    【讨论】:

      【解决方案7】:

      现在我正在使用这个:

      Dialoglar.Confirm = function (_title, _question, callback_OK) {
          var confirmArguments = arguments;
          bootbox.dialog({
              title: "<b>" + _title + "</b>",
              message: _question,
              buttons: {
                  success: {
                      label: "OK",
                      className: "btn-success",
                      callback: function () {
                          if (typeof(callback_OK) == "function") {                            callback_OK.apply(this,Array.prototype.slice.call(confirmArguments, 3));
                          }
                      }
                  },
                  danger: {
                      label: "Cancel",
                      className: "btn-danger",
                      callback: function () {
                          $(this).hide();
                      }
                  }
              }
          });
      };
      

      【讨论】:

        【解决方案8】:
        function a(a, b) {
            return a + b
        };
        
        function call_a() {
            return a.apply(a, Array.prototype.slice.call(arguments, 0));
        }
        
        console.log(call_a(1, 2))
        

        控制台:3

        【讨论】:

          【解决方案9】:

          您不能直接传递arguments 数组吗?

          function mainfunc (func){
              // remove the first argument containing the function name
              arguments.shift();
              window[func].apply(null, arguments);
          }
          
          function calledfunc1(args){
              // Do stuff here
          }
          
          function calledfunc2(args){
              // Do stuff here
          }
          
          mainfunc('calledfunc1','hello','bye');
          mainfunc('calledfunc2','hello','bye','goodbye');
          

          【讨论】:

          • 不,你不能,因为“arguments”不是一个数组,而是一个类似数组的对象,并且没有 shift() 成员。您需要将参数 1 复制到 arguments.length 到一个新数组并将该数组传递给 apply()。
          【解决方案10】:

          如果有人仍在寻找带有动态参数的动态函数调用 -

          callFunction("aaa('hello', 'world')");
          
              function callFunction(func) {
                          try
                          {
                              eval(func);
                          }
                          catch (e)
                          { }
                      }
              function aaa(a, b) {
                          alert(a + ' ' + b);
                      }
          

          【讨论】:

          • 不不不不。还有,没有。
          • 在 2021 年,这将是热闹的 10 倍!
          猜你喜欢
          • 2018-03-06
          • 1970-01-01
          • 2015-05-31
          • 2015-09-01
          • 1970-01-01
          • 2012-01-28
          • 2019-12-17
          • 1970-01-01
          • 2017-09-21
          相关资源
          最近更新 更多