Numero variabile di parametri JavaScript per funzionare

Esiste un modo per consentire le vars “illimitate” per una funzione in JavaScript?

Esempio:

load(var1, var2, var3, var4, var5, etc...) load(var1) 

Certo, basta usare gli arguments object.

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

Un’altra opzione è quella di passare i tuoi argomenti in un object di contesto.

 function load(context) { // do whatever with context.name, context.address, etc } 

e usalo in questo modo

 load({name:'Ken',address:'secret',unused:true}) 

Questo ha il vantaggio di poter aggiungere tutti gli argomenti con nome che si desidera e la funzione può usarli (o meno) come meglio crede.

Nei browser recenti, puoi accettare il numero variabile di argomenti con questa syntax:

 function my_log(...args) { //args is an Array console.log(args); //You can pass this array as parameters to another function console.log(...args); } 

Sono d’accordo con la risposta di Ken come la più dynamic e mi piace fare un ulteriore passo avanti. Se si tratta di una funzione chiamata più volte con argomenti diversi, utilizzo la progettazione di Ken ma aggiungo i valori predefiniti:

 function load(context) { var defaults = { parameter1: defaultValue1, parameter2: defaultValue2, ... }; var context = extend(defaults, context); // do stuff } 

In questo modo, se si hanno molti parametri ma non è necessario necessariamente impostarli con ogni chiamata alla funzione, è sufficiente specificare i valori non predefiniti. Per il metodo estendi, puoi utilizzare il metodo di estensione di jQuery ( $.extend() ), creare il tuo o utilizzare il seguente:

 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]; } 

Questo unirà l'object contesto con i valori predefiniti e riempirà tutti i valori indefiniti nel tuo object con i valori predefiniti.

Sì, proprio così:

 function load() { var var0 = arguments[0]; var var1 = arguments[1]; } load(1,2); 

Anche se in generale sono d’accordo sul fatto che l’approccio agli argomenti con nome sia utile e flessibile (a meno che non ti interessi dell’ordine, nel qual caso gli argomenti sono più semplici), ho delle preoccupazioni riguardo al costo dell’approccio mbeasley (usando i default e le estensioni). Questa è una quantità enorme di costi da sostenere per tirare valori predefiniti. Innanzitutto, i valori predefiniti sono definiti all’interno della funzione, quindi vengono ripopolati in ogni chiamata. In secondo luogo, puoi facilmente leggere i valori nominati e impostare i valori predefiniti allo stesso tempo usando ||. Non è necessario creare e unire ancora un altro nuovo object per ottenere queste informazioni.

 function load(context) { var parameter1 = context.parameter1 || defaultValue1, parameter2 = context.parameter2 || defaultValue2; // do stuff } 

Si tratta approssimativamente della stessa quantità di codice (forse leggermente più), ma dovrebbe essere una frazione del costo di runtime.

Come già detto, è ansible utilizzare l’object arguments per recuperare un numero variabile di parametri di funzione.

Se si desidera chiamare un’altra funzione con gli stessi argomenti, utilizzare apply . È anche ansible aggiungere o rimuovere argomenti convertendo gli arguments in un array. Ad esempio, questa funzione inserisce del testo prima di accedere alla console:

 log() { let args = Array.prototype.slice.call(arguments); args = ['MyObjectName', this.id_].concat(args); console.log.apply(console, args); } 

È preferibile utilizzare la syntax dei parametri di rest come indicato da Ramast.

 function (a, b, ...args) {} 

Voglio solo aggiungere qualche bella proprietà dell’argomento … args

  1. È un array e non un object come argomenti. Questo ti permette di applicare funzioni come la mappa o ordinare direttamente.
  2. Non include tutti i parametri ma solo quello da esso passato. Es. Funzione (a, b, … args) in questo caso args contiene l’argomento 3 a arguments.length

Utilizzare l’object arguments quando si trova all’interno della funzione per accedere a tutti gli argomenti inoltrati.

Mentre @roufamatic ha mostrato l’uso della parola chiave arguments e @Ken ha mostrato un ottimo esempio di un object per l’utilizzo, non mi sento veramente interessato a ciò che sta succedendo in questa istanza e posso confondere futuri lettori o infondere una ctriggers pratica in quanto non esplicitamente affermando una funzione / metodo è destinato a prendere una quantità variabile di argomenti / parametri.

 function varyArg () { return arguments[0] + arguments[1]; } 

Quando un altro sviluppatore sta esaminando il tuo codice, è molto facile presumere che questa funzione non prenda parametri. Soprattutto se lo sviluppatore non è al corrente della parola chiave arguments . Per questo motivo è una buona idea seguire una linea guida di stile ed essere coerenti. Userò Google per tutti gli esempi.

Diamo esplicitamente la stessa funzione ha parametri variabili:

 function varyArg (var_args) { return arguments[0] + arguments[1]; } 

Parametro object VS var_args

Ci possono essere momentjs in cui un object è necessario in quanto è l’unico metodo di best practice approvato e considerato di una mappa di dati. Gli array associativi sono disapprovati e scoraggiati.

SIDENOTE: la parola chiave arguments restituisce effettivamente un object utilizzando i numeri come chiave. L’eredità prototipale è anche la famiglia di oggetti. Vedere la fine della risposta per l’uso corretto dell’array in JS

In questo caso possiamo anche dichiararlo esplicitamente. Nota: questa convenzione di denominazione non è fornita da Google ma è un esempio di dichiarazione esplicita del tipo di un parametro. Questo è importante se stai cercando di creare un modello tipizzato più rigido nel tuo codice.

 function varyArg (args_obj) { return args_obj.name+" "+args_obj.weight; } varyArg({name: "Brian", weight: 150}); 

Quale scegliere?

Questo dipende dalle esigenze della tua funzione e del programma. Se, ad esempio, si sta semplicemente cercando di restituire una base di valore su un processo iterativo su tutti gli argomenti passati, quasi sicuramente si manterrà la parola chiave arguments . Se hai bisogno di una definizione per i tuoi argomenti e la mapping dei dati, allora il metodo dell’object è la strada da percorrere. Diamo un’occhiata a due esempi e poi abbiamo finito!

Utilizzo degli argomenti

 function sumOfAll (var_args) { return arguments.reduce(function(a, b) { return a + b; }, 0); } sumOfAll(1,2,3); // returns 6 

Utilizzo dell’object

 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 

Accesso a una matrice anziché a un object (“… args” Il parametro rest)

Come menzionato all’inizio della risposta, la parola chiave arguments restituisce effettivamente un object. Per questo motivo sarà necessario chiamare qualsiasi metodo che si desidera utilizzare per un array. Un esempio di questo:

 Array.prototype.map.call(arguments, function (val, idx, arr) {}); 

Per evitare questo, usa il parametro rest:

 function varyArgArr (...var_args) { return var_args.sort(); } varyArgArr(5,1,3); // returns 1, 3, 5 

Tieni presente che il passaggio di un object con proprietà denominate come suggerito da Ken aggiunge il costo di allocare e rilasciare l’object temporaneo in ogni chiamata. Passare argomenti normali per valore o riferimento sarà generalmente il più efficiente. Per molte applicazioni anche se le prestazioni non sono critiche, ma per alcuni può essere.