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

IT技术 javascript variadic-functions
2021-01-24 02:43:30

是否可以从数组向 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,能够接受可变参数并发送它们是一个很棒的模式。例如

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 中发送一个数组作为参数数组?

6个回答

更新:从 ES6 开始,您可以在调用函数时简单地使用spread 语法

func(...arr);

由于 ES6 同样,如果您希望将参数视为数组,则还可以在参数列表中使用 spread 语法,例如:

function func(...args) {
  args.forEach(arg => console.log(arg))
}

const values = ['a', 'b', 'c']
func(...values)
func(1, 2, 3)

并且您可以将它与普通参数结合使用,例如,如果您想分别接收前两个参数并将其余参数作为数组接收:

function func(first, second, ...theRest) {
  //...
}

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

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

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

传播语法比apply如果您不需要this在函数调用中设置更短更“甜蜜” ,这就是要走的路。

这是一个应用示例,这是以前的方法:

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

function func() {
  console.log(this); // 'test'
  console.log(arguments.length); // 3

  for(var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }

};

func.apply('test', arr);

现在,我只建议apply仅在需要从数组中传递任意数量的参数设置this时才使用applytake 是this作为第一个参数值,将在函数调用时使用,如果我们null在非严格代码中使用,则this关键字将引用内部的全局对象(窗口)func,在严格模式下,当显式使用 'use strict ' 或在 ES module中,null将被使用。

另请注意,该arguments对象并不是真正的数组,您可以通过以下方式对其进行转换:

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

在 ES6 中:

const argsArray = [...arguments] // or Array.from(arguments)

但是arguments由于扩展语法,您现在很少直接使用该对象。

谢谢, apply 可以解决问题,在这种情况下调用不起作用。是不是写错了?
2021-03-11 02:43:30
注意:我继续写了我自己的答案
2021-03-13 02:43:30
Array.prototype.slice.call(arguments);阻止浏览器 JS 优化,如 V8。详情在这里
2021-03-14 02:43:30
1.显然,arguments计划弃用点差运算符我没有这方面的消息来源,但我在某处听说过。2. MDN 声明slicearguments对象上使用会阻止在 V8 等引擎中进行优化。他们建议使用“被鄙视的数组构造函数”、Array.from(arguments)、 或[...arguments]你愿意更新你对 ES2015 的回答吗?
2021-03-25 02:43:30
如果函数实际上是类的成员,你会怎么做?这是正确的吗?theObject.member.apply(theObject, arguments);
2021-04-04 02:43:30

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

要以“解压”形式传递参数数组,您可以使用 apply,如下所示(参见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);

图示传播运营商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');

请注意传播的尴尬语法。通常的语法sprintf('The %s %s fox jumps over the %s dog.', ...arr);不被支持您可以在此处找到ES6 兼容性表

还要注意 的使用for...of,另一个 ES6 添加。使用for...in数组是一个坏主意

Firefox 和 Chrome 现在支持传播的正常​​语法
2021-04-08 02:43:30

ES2015 有两种方法。

arguments对象

该对象内置于函数中,它适当地引用了函数的参数。但是,从技术上讲,它不是数组,因此典型的数组操作不适用于它。建议的方法是使用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 语言的一种古老的 pre-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

它非常通用,也可以用在函数的参数列表(“其余参数”)中,以记录良好的方式指定可变参数:

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

我更喜欢传播运算符。它是干净的和自我记录的。

感谢您提供更新的答案,这篇文章早于 ES 2015,所以我很高兴您填写了更多最近的选项
2021-03-25 02:43:30

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

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