Можно ли отправить переменное количество аргументов функции 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 есть два метода.
Этот объект встроен в функции, и он соответствующим образом ссылается на аргументы функции. Однако это не технически массив, поэтому типичные операции с массивами на нем не будут работать. Предлагаемый метод заключается в использовании 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);
}
};