Есть ли способ разрешить "неограниченное" количество переменных для функции в JavaScript?
Пример:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Есть ли способ разрешить "неограниченное" количество переменных для функции в JavaScript?
Пример:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Конечно, просто используйте объект arguments.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments - это особый объект, подобный массиву, что означает, что он имеет длину, но не имеет других функций массива. См. developer.mozilla.org/en-US/docs. / Web / JavaScript / Reference / для получения дополнительной информации и этот ответ: stackoverflow.com/a/13145228/1766230 а>
- person Luke; 22.04.2015
length. Сюда входит объект arguments. Зная это и что метод concat возвращает копию «массива», который он вызвал, мы можем легко преобразовать объект arguments в реальный массив, например: var args = [].concat.call(arguments). Некоторые люди предпочитают вместо этого использовать Array.prototype.concat.call, но мне нравится [], они короткие и милые!
- person Stijn de Witt; 11.11.2016
Function.arguments устарело, но не ванильный объект arguments. См. developer.mozilla.org/en-US/docs. / Web / JavaScript / Reference /.
- person roufamatic; 06.09.2017
call для вызова функции concat. Если вы вызовете его напрямую, объект будет добавлен. Уловка с использованием call заключается в том, что concat будет вызываться с arguments, поскольку это this. Таким образом, он клонирует объект arguments в реальный массив.
- person Stijn de Witt; 25.06.2018
[...arguments].join()
- person Willian D. Andrade; 22.07.2019
В (большинстве) последних браузеров вы можете принимать переменное количество аргументов с помощью этого синтаксиса:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Вот небольшой пример:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
0: "a"
1: "b"
2: "c"
3: "d"
length: 4
Документация и другие примеры здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters.
Другой вариант - передать аргументы в объекте контекста.
function load(context)
{
// do whatever with context.name, context.address, etc
}
и используйте это так
load({name:'Ken',address:'secret',unused:true})
Это имеет то преимущество, что вы можете добавить столько именованных аргументов, сколько захотите, и функция может использовать их (или нет) по своему усмотрению.
context с помощью кода и передать его до того, как он будет использован.
- person Nate C-K; 29.01.2014
Я согласен с ответом Кена как с наиболее динамичным, и мне нравится делать еще один шаг вперед. Если это функция, которую вы вызываете несколько раз с разными аргументами - я использую дизайн Кена, но затем добавляю значения по умолчанию:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
Таким образом, если у вас много параметров, но не обязательно устанавливать их при каждом вызове функции, вы можете просто указать значения, отличные от значений по умолчанию. Для метода расширения вы можете использовать метод расширения jQuery ($.extend()), создать свой собственный или использовать следующее:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
Это объединит объект контекста со значениями по умолчанию и заполнит все неопределенные значения в вашем объекте значениями по умолчанию.
_.defaults() - очень хорошая альтернатива слиянию указанных аргументов и аргументов по умолчанию.
- person mbeasley; 14.02.2013
Как указал Рамаст, предпочтительно использовать синтаксис параметров отдыха.
function (a, b, ...args) {}
Я просто хочу добавить приятное свойство аргумента ... args
- Это массив, а не объект, подобный аргументам. Это позволяет вам напрямую применять такие функции, как карта или сортировка.
- Он не включает все параметры, а только тот, который передается от него. Например. function (a, b, ... args) в этом случае args содержит аргумент 3 для arguments.length
Да вот так:
function load()
{
var var0 = arguments[0];
var var1 = arguments[1];
}
load(1,2);
Как уже упоминалось, вы можете использовать объект arguments для получения переменного количества параметров функции.
Если вы хотите вызвать другую функцию с теми же аргументами, используйте apply. Вы даже можете добавлять или удалять аргументы, преобразовывая arguments в массив. Например, эта функция вставляет текст перед выходом на консоль:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Хотя я в целом согласен с тем, что подход с именованными аргументами является полезным и гибким (если вы не заботитесь о порядке, в этом случае аргументы проще всего), у меня есть опасения по поводу стоимости подхода mbeasley (с использованием значений по умолчанию и расширений). Это огромные затраты на выборку значений по умолчанию. Во-первых, значения по умолчанию определяются внутри функции, поэтому они обновляются при каждом вызове. Во-вторых, вы можете легко прочитать названные значения и одновременно установить значения по умолчанию, используя ||. Нет необходимости создавать и объединять еще один новый объект, чтобы получить эту информацию.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
Это примерно такой же объем кода (возможно, немного больше), но он должен составлять лишь часть стоимости времени выполнения.
(parameter1=context.parameter1)===undefined && (parameter1=defaultValue1) или для меньшего объема кода небольшая вспомогательная функция, например: function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1), предоставит альтернативные шаблоны. Однако моя точка зрения остается неизменной: создание дополнительных объектов для каждого вызова функции и запуск дорогостоящих циклов для установки пары значений по умолчанию - это сумасшедшие накладные расходы.
- person mcurland; 29.08.2014
Хотя @roufamatic действительно продемонстрировал использование ключевого слова arguments, а @Ken показал отличный пример объекта для использования, я не чувствую, что действительно обращает внимание на то, что происходит в этом случае, и может сбить с толку будущих читателей или привить плохую практику, например, явное указание функции. / method предназначен для приема переменного количества аргументов / параметров.
function varyArg () {
return arguments[0] + arguments[1];
}
Когда другой разработчик просматривает ваш код, очень легко предположить, что эта функция не принимает параметров. Особенно, если этот разработчик не знаком с ключевым словом arguments. Из-за этого рекомендуется следовать руководству по стилю и быть последовательным. Я буду использовать Google для всех примеров.
Давайте явно укажем, что одна и та же функция имеет переменные параметры:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Могут быть случаи, когда объект необходим, поскольку это единственный одобренный и признанный передовой метод построения карты данных. Ассоциативные массивы не одобряются и не приветствуются.
SIDENOTE: ключевое слово arguments фактически возвращает объект, используя числа в качестве ключа. Прототипное наследование также является семейством объектов. См. Конец ответа для правильного использования массива в JS
В этом случае мы также можем указать это явно. Примечание: это соглашение об именах не предоставляется Google, но является примером явного объявления типа параметра. Это важно, если вы хотите создать в своем коде более строгий типизированный шаблон.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Это зависит от ваших функций и потребностей программы. Если, например, вы просто хотите вернуть базу значений в итеративном процессе по всем переданным аргументам, то, безусловно, придерживайтесь ключевого слова arguments. Если вам нужно определение ваших аргументов и сопоставление данных, тогда метод объекта - это то, что вам нужно. Давайте посмотрим на два примера, и на этом все готово!
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Как упоминалось в начале ответа, ключевое слово arguments фактически возвращает объект. Из-за этого необходимо будет вызвать любой метод, который вы хотите использовать для массива. Пример этого:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
Чтобы этого не произошло, используйте параметр rest:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Используйте объект arguments внутри функции, чтобы иметь доступ ко всем переданным аргументам.
Имейте в виду, что передача объекта с именованными свойствами, как предложил Кен, увеличивает стоимость выделения и освобождения временного объекта для каждого вызова. Как правило, наиболее эффективной будет передача обычных аргументов по значению или ссылке. Для многих приложений производительность не критична, но для некоторых может.