首页 文章

是否可以向JavaScript函数发送可变数量的参数?

提问于
浏览
148

是否可以从数组中向JavaScript函数发送可变数量的参数?

var arr = ['a','b','c']

var func = function()
{
    // debug 
    alert(arguments.length);
    //
    for(arg in arguments)
        alert(arg);
}

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'

我最近写了很多Python,这是一个很好的模式,能够接受varargs并发送它们 . 例如

def func(*args):
   print len(args)
   for i in args:
       print i

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(*arr) // prints 4 which is what I want, then 'a','b','c','d'

是否有可能在JavaScript中发送一个数组来处理 as 参数数组?

12 回答

  • 69

    是的你可以传递变量号 . 函数的参数 . 您可以使用 apply 来实现此目的 .

    例如 . :

    var arr = ["Hi","How","are","you"];
    
    function applyTest(){
        var arg = arguments.length;
        console.log(arg);
    }
    
    applyTest.apply(null,arr);
    
  • 22

    使用apply

    var arr = ['a','b','c'];
    
    var func = function() {
      alert(arguments.length);
    
      for(var i = 0; i < arguments.length; i++) {
        alert(arguments[i]);
      }
    
    };
    
    func.apply(null, arr);
    

    请注意, null 用作apply的第一个参数,它将 this 关键字设置为 func 内的Global对象(窗口) .

    另请注意,arguments对象实际上不是一个数组,您可以通过以下方式将其转换为:

    var argsArray = Array.prototype.slice.call(arguments);
    

    也许对您有用,您可以知道函数需要多少个参数:

    var test = function (one, two, three) {}; 
    test.length == 3;
    

    但无论如何你可以传递任意数量的参数......

  • 1

    您实际上可以将任意数量的值传递给任何javascript函数 . 显式命名的参数将获得前几个值,但ALL参数将存储在arguments数组中 .

    要在"unpacked"表单中传递arguments数组,可以使用apply,如下所示(c.f. Functional Javascript):

    var otherFunc = function() {
       alert(arguments.length); // Outputs: 10
    }
    
    var myFunc = function() {
      alert(arguments.length); // Outputs: 10
      otherFunc.apply(this, arguments);
    }
    myFunc(1,2,3,4,5,6,7,8,9,10);
    
  • 0

    splatspread运算符是ES6的一部分,ES6是计划的下一版Javascript . 到目前为止只有Firefox支持它们 . 此代码适用于FF16:

    var arr = ['quick', 'brown', 'lazy'];
    
    var sprintf = function(str, ...args)
    {
        for (arg of args) {
            str = str.replace(/%s/, arg);
        }
        return str;
    }
    
    sprintf.apply(null, ['The %s %s fox jumps over the %s dog.', ...arr]);
    sprintf('The %s %s fox jumps over the %s dog.', 'slow', 'red', 'sleeping');
    

    注意传播的awkard语法 . sprintf('The %s %s fox jumps over the %s dog.', ...arr); 的通常语法是not yet supported . 你可以找到an ES6 compatibility table here .

    另请注意使用for...of,另外添加ES6 . 对数组使用 for...ina bad idea .

  • 8

    ES2015有两种方法 .

    参数Object

    该对象内置于函数中,它适当地引用函数的参数 . 但是,从技术上讲,它不是一个数组,所以典型的数组操作不适用于它 . 建议的方法是使用 Array.from 或扩展运算符从中创建数组 .

    我见过使用 slice 提到的其他答案 . 不要那样做 . 它会阻止优化(来源:MDN) .

    Array.from(arguments)
    [...arguments]
    

    但是,我认为 arguments 是有问题的,因为它隐藏了函数接受的输入 . arguments 函数通常是这样写的:

    function mean(){
        let args = [...arguments];
        return args.reduce((a,b)=>a+b) / args.length;
    }
    

    有时,函数头像下面这样编写,以类似C的方式记录参数:

    function mean(/* ... */){ ... }
    

    但这种情况很少见 .

    至于为什么它有问题,以C为例 . C向后兼容一种称为K&R C的古老的ANSI前语言.K&R C允许函数原型具有空参数列表 .

    int myFunction();
    /* This function accepts unspecified parameters */
    

    ANSI C为 varargs... )提供了工具, void 用于指定空参数列表 .

    int myFunction(void);
    /* This function accepts no parameters */
    

    许多人在希望函数采用零参数时无意中声明了具有 unspecified 参数列表( int myfunction(); )的函数 . 这在技术上是一个错误,因为该函数将接受参数 . 任意数量的 .

    C中适当的 varargs 函数采用以下形式:

    int myFunction(int nargs, ...);
    

    JavaScript实际上确实有类似的东西 .

    传播操作员/休息参数

    实际上,我已经向你展示了传播运营商 .

    ...name
    

    它非常通用,也可以在函数的参数列表(“休息参数”)中使用,以一种很好的文档方式指定varargs:

    function mean(...args){
        return args.reduce((a,b)=>a+b) / args.length;
    }
    

    或者作为lambda表达式:

    ((...args)=>args.reduce((a,b)=>a+b) / args.length)(1,2,3,4,5); // 3
    

    我更喜欢传播运营商 . 它干净,自我记录 .

  • 2

    apply 函数有两个参数;对象 this 将绑定到,并且参数用数组表示 .

    some_func = function (a, b) { return b }
    some_func.apply(obj, ["arguments", "are", "here"])
    // "are"
    
  • 2

    它被称为 splat 运算符 . 您可以使用 apply 在JavaScript中执行此操作:

    var arr = ['a','b','c','d'];
    var func = function() {
        // debug 
        console.log(arguments.length);
        console.log(arguments);
    }
    func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
    func(arr); // prints 1, then 'Array'
    func.apply(null, arr);
    
  • 4

    使用ES6,您可以将rest parameters用于 varagrs . 这将获取参数列表并将其转换为数组 .

    function logArgs(...args) {
        console.log(args.length)
        for(let arg of args) {
            console.log(arg)
        }
    }
    
  • 168

    这是一个示例程序,用于计算变量参数和整数数组的整数之和 . 希望这可以帮助 .

    var CalculateSum = function(){
        calculateSumService.apply( null, arguments );
    }
    
    var calculateSumService = function(){
        var sum = 0;
    
        if( arguments.length === 1){
            var args = arguments[0];
    
            for(var i = 0;i<args.length; i++){
               sum += args[i]; 
            }
        }else{
            for(var i = 0;i<arguments.length; i++){
               sum += arguments[i]; 
            }        
        }
    
         alert(sum);
    
    }
    
    
    //Sample method call
    
    // CalculateSum(10,20,30);         
    
    // CalculateSum([10,20,30,40,50]);
    
    // CalculateSum(10,20);
    
  • 7
    (function(window) {
      var proxied = window.alert;
      window.alert = function() {
        return proxied.apply(window, arguments);
      };
    }(this));
    
    alert(13, 37);
    
  • 5

    对于那些从Passing variable number of arguments from one function to another重定向的人(应将 not 标记为此问题的副本):

    如果您尝试将可变数量的参数从一个函数传递到另一个函数,那么从JavaScript 1.8.5开始,您只需在第二个函数上调用 apply() 并传入 arguments 参数:

    var caller = function()
    {
        callee.apply( null, arguments );
    }
    
    var callee = function()
    {
        alert( arguments.length );
    }
    
    caller( "Hello", "World!", 88 ); // Shows "3".
    

    Note: 第一个参数是要使用的 this 参数 . 传递 null 将从全局调用该函数上下文,即作为全局函数而不是某个对象的方法 .

    根据this document,ECMAScript 5规范重新定义了 apply() 方法以获取任何"generic array-like object",而不是严格的数组 . 因此,您可以直接将 arguments 列表传递给第二个函数 .

    在Chrome 28.0,Safari 6.0.5和IE 10中测试过 . 使用this JSFiddle进行测试 .

  • 0

    您是否希望函数对数组参数或变量参数作出反应?如果是后者,请尝试:

    var func = function(...rest) {
      alert(rest.length);
    
      // In JS, don't use for..in with arrays
      // use for..of that consumes array's pre-defined iterator
      // or a more functional approach
      rest.forEach((v) => console.log(v));
    };
    

    但是如果你想处理一个数组参数

    var fn = function(arr) {
      alert(arr.length);
    
      for(var i of arr) {
        console.log(i);
      }
    };
    

相关问题