Передать неизвестное количество аргументов в функцию javascript

85

Есть ли способ передать неизвестное количество аргументов, например:

var print_names = function(names) {
    foreach(name in names) console.log(name); // something like this
}

print_names('foo', 'bar', 'baz');

Кроме того, как мне узнать количество переданных аргументов?

Эйси
источник
Пока что публичный ответ переопределения - единственный, который описывает, как передать неизвестное количество аргументов (в вызов функции) (используя .apply). Остальные показывают, как читать неизвестное количество аргументов (из функции) (используя arguments).
Ben J

Ответы:

147

ES3 (или ES5, или старый Javascript)

Вы можете получить доступ к аргументам, переданным любой функции javascript, через волшебный argumentsобъект, который ведет себя аналогично массиву. Использование argumentsвашей функции будет выглядеть так

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

Важно отметить, что argumentsэто не массив. У MDC есть хорошая документация: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#Using_the_arguments_object

Если вы хотите превратить argumentsв массив, чтобы вы могли делать что-то вроде .slice()и .push()т. Д., Используйте что-то вроде этого:

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

ES6 / Машинопись

Есть способ лучше! Вам поможет новая функция параметров отдыха :

var print_names = function(...names) {
    for (let i=0; i<names.length; i++) console.log(names[i]);
}
ШЗ
источник
3
Спасибо за такой подробный и в то же время короткий + простой ответ :)
Mese
1
Ссылка на ES6 spread syntaxздесь совершенно неверна. Это rest parameterвы привели пример. Хороший ответ, но сбивает с толку то, что на него ссылаются какspread
Дренай
Спасибо за Ваш ответ! Я нашел , что это будет полезно статья объяснить , что происходит с Array.prototype.slice.call(arguments): medium.com/@andrewsburke/...
AnnieP
22

ES6 / ES2015

Воспользуйтесь синтаксисом остальных параметров .

function printNames(...names) {
  console.log(`number of arguments: ${names.length}`);
  for (var name of names) {
    console.log(name);
  }
}

printNames('foo', 'bar', 'baz');

Между параметрами rest и объектом arguments есть три основных различия:

  • остальные параметры - это только те, которым не было присвоено отдельное имя, в то время как объект arguments содержит все аргументы, переданные функции;
  • объект arguments не является реальным массивом, а остальные параметры являются экземплярами Array, что означает, что к нему можно напрямую применять такие методы, как sort, map, forEach или pop;
  • объект arguments имеет дополнительные специфические функции (например, свойство callee).
RationalDev нравится GoFundMonica
источник
Это имеет смысл для веб-разработки, которая обычно использует общий синтаксис PHP.
Дадан
13
var 
print_names = function() {
    console.log.apply( this, arguments );
};

print_names( 1, 2, 3, 4 );
общественное переопределение
источник
7
function print_args() {
    for(var i=0; i<arguments.length; i++)
        console.log(arguments[i])
}
Габи Пуркару
источник
6

Каждой вызываемой функции в JavaScript передается скрытый объект arguments.

Вы просто используете, arguments.lengthчтобы получить количество аргументов, переданных функции.

Чтобы перебрать аргументы, вы должны использовать цикл:

for(var i = arguments.length; i--) {
   var arg = arguments[i];
}

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

var args = Array.prototype.slice.call(arguments);
Яков Релкин
источник
3
Просто обратите внимание, что это не «настоящий» массив, это «подобный массиву» объект (с некоторыми особыми характеристиками), но чтобы использовать на нем «методы массива», вам необходимо преобразовать его, например var args = Array.prototype.slice.call(arguments);, var args = Array.apply(null, arguments);и т. Д. , есть много способов ...
Кристиан С. Сальвадо
4

arguments.length. вы можете использовать для него цикл for.

(function () {
    for (var a = [], i = arguments.length; i--;) {
        a.push(arguments[i]);
    };
    return a;
})(1, 2, 3, 4, 5, 6, 7, 8)
Медер Омуралиев
источник
@meder, я люблю использовать такие анонимные функции. Хороший пример! Кроме того, вам не хватает пары точек с запятой?
Джейкоб Релкин
@meder, Вставка точки с запятой в JavaScript #ftf
Джейкоб Релкин
@meder, действительно, точка с запятой после forблока не нужна, но я бы добавил ее в конец последней строки.
Кристиан С. Сальвадо
Почему вам нужно поместить функцию между ()?
ajsie
1
@weng, это про FunctionExpressionvs FunctionDeclaration, посмотрите эту статью .
Кристиан С. Сальвадо
2

Теперь намного лучше для ES6

function Example() {
    return {
        arguments: (...args) =>{
            args.map(a => console.log());
        }
    }
}

var exmpl = new Example();
exmpl.arguments(1, 2, 3, 'a', 'b', 'c');

надеюсь, это поможет

Сантьяго Посада
источник
0

Остальные параметры в ES6

const example = (...args) => {
  for (arg in args) {
    console.log(arg);
  }
}

Примечание: вы можете передать обычные параметры перед остальными параметрами.

const example = (arg1, ...args) => {
  console.log(arg1);
  for (arg in args) {
    console.log(arg);
  }
}
Куртис Штрейткер
источник
0

Вы можете использовать оператор spread / rest для сбора ваших параметров в массив, и тогда lengthмассив будет числом переданных вами параметров:

function foo(...names) {
    console.log(names);
    return names;
}

console.log(foo(1, 2, 3, 4).length);

Используя BabelJS, я преобразовал функцию в oldschool JS:

"use strict";

function foo() {
  for (var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++) {
    names[_key] = arguments[_key];
  }

  console.log(names);
  return names;
}
Лайош Арпад
источник
0

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

const print_names = (...args) => args.forEach(x => console.log(x));
Мабулу
источник
-4

Мне нравится это делать:

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

/**
 *  @param  params.one        A test parameter
 *  @param  params.two        Another one  
 **/
function test(params) {

    var one = params.one;
    if(typeof(one) == 'undefined') {
        throw new Error('params.one is undefined');
    }

    var two = params.two;
    if(typeof(two) == 'undefined') {
        throw new Error('params.two is undefined');
    }
}
Колин Салливан
источник
1
Вопрос был о неизвестном количестве аргументов.
Дизайн Адриан