Przekaż nieznaną liczbę argumentów do funkcji javascript


86

Czy istnieje sposób na przekazanie nieznanej liczby argumentów, takich jak:

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

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

Ponadto, jak uzyskać liczbę przekazanych argumentów?



Jak dotąd odpowiedź public override jest jedyną, która opisuje, jak przekazać nieznaną liczbę argumentów (do wywołania funkcji) (używając .apply). Pozostałe pokazują, jak odczytać nieznaną liczbę argumentów (z funkcji) (za pomocą arguments).
Ben J

Odpowiedzi:


147

ES3 (lub ES5 lub oldschoolowy Javascript)

Możesz uzyskać dostęp do argumentów przekazanych do dowolnej funkcji javascript poprzez magiczny argumentsobiekt, który zachowuje się podobnie do tablicy. Korzystanie argumentsz funkcji wyglądałoby tak

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

Należy zauważyć, że niearguments jest to tablica. MDC ma dobrą dokumentację na ten temat: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#Using_the_arguments_object

Jeśli chcesz przekształcić argumentssię w tablicę, aby móc robić takie rzeczy .slice(), .push()itp., Użyj czegoś takiego:

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

ES6 / Maszynopis

Jest lepszy sposób! Nowa funkcja parametrów odpoczynku zapewnia:

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

3
Dzięki za tak szczegółową i jednocześnie krótką + prostą odpowiedź :)
Mese

1
Odniesienie do ES6 spread syntaxjest tutaj dość niepoprawne. To jest rest parameterprzykład, który podałeś. Dobra odpowiedź, ale myląca, że ​​jest określana jakospread
Drenai

Dzięki za odpowiedź! Uważam, że jest to pomocny artykuł wyjaśniający, co się dzieje z Array.prototype.slice.call(arguments): medium.com/@andrewsburke/ ...
AnnieP

22

ES6 / ES2015

Skorzystaj z pozostałej składni parametru .

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

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

Istnieją trzy główne różnice między parametrami rest a obiektem arguments:

  • pozostałe parametry to tylko te, którym nie nadano oddzielnej nazwy, podczas gdy obiekt arguments zawiera wszystkie argumenty przekazane do funkcji;
  • obiekt arguments nie jest prawdziwą tablicą, podczas gdy pozostałe parametry są instancjami Array, co oznacza, że ​​metody takie jak sort, map, forEach lub pop można zastosować bezpośrednio do niego;
  • obiekt arguments ma dodatkową, specyficzną dla siebie funkcję (taką jak właściwość callee).

Ma to sens w przypadku tworzenia stron internetowych, które zwykle używają wspólnej składni PHP.
Dadan


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

6

Do każdej funkcji w JavaScript przekazywany jest ukryty obiekt o nazwie arguments.

Możesz po prostu użyć, arguments.lengthaby uzyskać liczbę argumentów przekazanych do funkcji.

Aby iterować przez argumenty, użyłbyś pętli:

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

Zauważ, że argumentsnie jest to prawdziwa tablica, więc jeśli potrzebujesz jej jako tablicy, przekonwertujesz ją w następujący sposób:

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

3
Wystarczy pamiętać, że nie jest to „prawdziwy” array, jest to „array-like” obiektu (z pewnymi szczególnymi cechami), ale w użyciu metody „Array” na niego, trzeba będzie przekształcić to, na przykład var args = Array.prototype.slice.call(arguments);, var args = Array.apply(null, arguments);itd , istnieje wiele sposobów ...
Christian C. Salvadó

4

arguments.length. możesz użyć na nim pętli for.

(function () {
    for (var a = [], i = arguments.length; i--;) {
        a.push(arguments[i]);
    };
    return a;
})(1, 2, 3, 4, 5, 6, 7, 8)

@meder, uwielbiam używać takich anonimowych funkcji. Niezły przykład! Czy brakuje tam kilku średników?
Jacob Relkin

@meder, Wstawienie średnika w JavaScript #ftf
Jacob Relkin

@meder, rzeczywiście, po prostu średnik po forbloku nie jest potrzebny, jednak dodałbym jeden na końcu ostatniej linii.
Christian C. Salvadó

Dlaczego musisz umieścić funkcję między ()?
ajsie

1
@weng, chodzi o FunctionExpressionvs FunctionDeclaration, sprawdź ten artykuł .
Christian C. Salvadó

2

Znacznie lepiej teraz dla ES6

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

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

mam nadzieję, że to pomoże


0

Parametry odpoczynku w ES6

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

Uwaga: możesz przekazać zwykłe parametry przed pozostałymi parametrami

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

0

Możesz użyć operatora spread / rest, aby zebrać parametry w tablicy, a następnie lengthtablica będzie liczbą przekazanych parametrów:

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

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

Używając BabelJS przekonwertowałem funkcję na oldschoolowy 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

Możesz utworzyć funkcję za pomocą operatora spread / rest i od tego momentu osiągnąłeś swój cel. Spójrz na fragment poniżej.

const print_names = (...args) => args.forEach(x => console.log(x));


-4

Lubię to robić:

To nie pomoże, jeśli nie znasz liczby argumentów, ale pomoże, jeśli nie chcesz zapamiętać ich kolejności.

/**
 *  @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
Pytanie dotyczyło nieznanej liczby argumentów.
Projekt Adriana
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.