Можно ли отправить переменное количество аргументов функции JavaScript?

Можно ли отправить переменное количество аргументов функции 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 отправить массив, который будет обрабатываться массивом аргументов как?

Ответ 1

Обновление: начиная с ES6, вы можете просто использовать синтаксис распространения при вызове функции:

func(...arr);

Так как ES6 также, если вы собираетесь обрабатывать свои аргументы как массив, вы также можете использовать синтаксис распространения в списке параметров, например:

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. apply принимает this значение this в качестве первых аргументов, которые будут использоваться при вызове функции. Если мы используем null в нестрогом коде, ключевое слово this будет ссылаться на глобальный объект (окно) внутри func в строгом режиме, когда Явно используя 'use strict' или в модулях ES, будет использоваться null.

Также обратите внимание, что объект arguments не является на самом деле массивом, его можно преобразовать следующим образом:

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

И в ES6:

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

Но вы редко используете объект arguments прямо сейчас, благодаря синтаксису распространения.

Ответ 2

Фактически вы можете передать столько значений, сколько хотите для любой функции javascript. Явным образом названные параметры получат первые несколько значений, но ВСЕ параметры будут сохранены в массиве аргументов.

Чтобы передать массив аргументов в "распакованной" форме, вы можете использовать apply, например (c.f. Функциональный 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);

Ответ 3

Операторы splat и spread являются частью 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); пока не поддерживается. Здесь вы можете найти таблицу совместимости ES6.

Обратите внимание также на использование for...of другого дополнения ES6. Использование for...in для массивов - плохая идея.

Ответ 4

На ES2015 есть два метода.

arguments 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-like:

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

Но это редко.

Что касается того, почему это проблематично, возьмите C, например. C обратно совместим с древним диалектом ANSI ANSI, известным как K & R C. 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();), когда они ожидают, что функция примет нулевые аргументы. Это технически ошибка, потому что функция будет принимать аргументы. Любое их число.

Правильная функция varargs в C принимает вид:

int myFunction(int nargs, ...);

И у JavaScript действительно есть что-то похожее на это.

Параметры оператора спреда/останова

На самом деле, я уже показал вам оператора распространения.

...name

Он довольно универсален и может также использоваться в списке аргументов функции ("параметры отдыха"), чтобы указать параметры varargs в хорошо документированном виде:

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

Или как выражение лямбда:

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

Я предпочитаю оператора распространения. Он чист и самодокументирован.

Ответ 5

Функция apply принимает два аргумента; объект this будет привязан к и аргументам, представленным массивом.

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

Ответ 6

Он называется оператором splat. Вы можете сделать это в JavaScript с помощью apply:

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); 

Ответ 7

С ES6 вы можете использовать остальные параметры для varagrs. Это берет список аргументов и преобразует его в массив.

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

Ответ 8

(function(window) {
  var proxied = window.alert;
  window.alert = function() {
    return proxied.apply(window, arguments);
  };
}(this));

alert(13, 37);

Ответ 9

Это примерная программа для вычисления суммы целых чисел для переменных аргументов и массива для целых чисел. Надеюсь, это поможет.

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);

Ответ 10

Для тех, кто перенаправлен сюда из Передача переменной количества аргументов из одной функции в другую (которая должна не быть отмечена как дубликат этого вопроса):

Если вы пытаетесь передать переменное количество аргументов из одной функции в другую, поскольку 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".

Примечание.. Первый аргумент - это параметр this. Передача null вызовет функцию из глобального контекста, т.е. Как глобальную функцию вместо метода некоторого объекта.

Согласно этот документ, спецификация ECMAScript 5 переопределила метод apply(), чтобы взять любой "общий объект, подобный массиву", вместо этого строго Массив. Таким образом, вы можете напрямую передать список arguments во вторую функцию.

Протестировано в Chrome 28.0, Safari 6.0.5 и IE 10. Попробуйте этот JSFiddle.

Ответ 11

Да, вы можете передать переменную no. аргументов функции. Вы можете использовать apply для достижения этой цели.

Например:

var arr = ["Hi","How","are","you"];

function applyTest(){
    var arg = arguments.length;
    console.log(arg);
}

applyTest.apply(null,arr);

Ответ 12

Вы хотите, чтобы ваша функция реагировала на аргумент массива или переменные аргументы? Если последнее, попробуйте:

var func = function(...rest) {
  alert(rest.length);

  // In JS, don't use for..in with arrays
  // use for..of that consumes array 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);
  }
};