使用动态数量的参数调用动态函数[重复]

Posted

技术标签:

【中文标题】使用动态数量的参数调用动态函数[重复]【英文标题】: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');

【问题讨论】:

apply()php 等效项是 call_user_func_array()。 phpjs.org/functions/call_user_func_array 解决方案也使用它。 【参考方案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");

【讨论】:

击败我 :) developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/… 获取更详细的文档 这是最合适的解决方案,但在参数中它会包含函数的名称(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 倍!

以上是关于使用动态数量的参数调用动态函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python - 动态更改参数数量[重复]

如何通过id检索动态数量的元素[重复]

在参数中调用具有多个动态元组的 Python 函数 (geopy.distance.great_circle()) [重复]

Python函数的动态参数[重复]

在django中动态添加参数到queryset过滤器调用[重复]

传递动态大小的数组(不允许使用参数)[重复]