Existe-t-il un moyen d'autoriser les variables "illimitées" pour une fonction en JavaScript?
Exemple:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Existe-t-il un moyen d'autoriser les variables "illimitées" pour une fonction en JavaScript?
Exemple:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Réponses:
Bien sûr, utilisez simplement l' arguments
objet.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments
est un objet spécial "de type tableau", ce qui signifie qu'il a une longueur, mais pas d'autres fonctions de tableau. Voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… pour plus d'informations et cette réponse: stackoverflow.com/a/13145228/1766230
length
propriété. Cela inclut l' arguments
objet. Sachant cela, et que la méthode concat
retourne une copie du « tableau » , il est appelé, nous pouvons facilement convertir l' arguments
objet vers un tableau comme celui - ci: var args = [].concat.call(arguments)
. Certaines personnes préfèrent utiliser à la Array.prototype.concat.call
place, mais j'aime le []
, elles sont courtes et douces!
[...arguments].join()
Dans les navigateurs les plus récents, vous pouvez accepter un nombre variable d'arguments avec cette syntaxe:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Voici un petit exemple:
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
Documentation et autres exemples ici: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
Une autre option consiste à passer vos arguments dans un objet contextuel.
function load(context)
{
// do whatever with context.name, context.address, etc
}
et l'utiliser comme ça
load({name:'Ken',address:'secret',unused:true})
Cela a l'avantage que vous pouvez ajouter autant d'arguments nommés que vous le souhaitez, et la fonction peut les utiliser (ou non) comme bon lui semble.
context
argument avec du code et le transmettre avant qu'il ne soit utilisé.
Je suis d'accord avec la réponse de Ken comme étant la plus dynamique et j'aime aller plus loin. Si c'est une fonction que vous appelez plusieurs fois avec des arguments différents - j'utilise la conception de Ken mais j'ajoute ensuite des valeurs par défaut:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
De cette façon, si vous avez de nombreux paramètres mais n'avez pas nécessairement besoin de les définir à chaque appel à la fonction, vous pouvez simplement spécifier les valeurs par défaut. Pour la méthode extend, vous pouvez utiliser la méthode extend ( $.extend()
) de jQuery , créer la vôtre ou utiliser ce qui suit:
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];
}
Cela fusionnera l'objet contextuel avec les valeurs par défaut et remplira toutes les valeurs non définies dans votre objet avec les valeurs par défaut.
_.defaults()
méthode Underscore est une très bonne alternative pour fusionner les arguments spécifiés et par défaut.
Il est préférable d'utiliser la syntaxe des paramètres de repos comme l'a souligné Ramast.
function (a, b, ...args) {}
Je veux juste ajouter une belle propriété de l'argument ... args
- C'est un tableau et non un objet comme des arguments. Cela vous permet d'appliquer des fonctions comme la carte ou de trier directement.
- Il n'inclut pas tous les paramètres mais seulement celui qui en est passé. Par exemple, la fonction (a, b, ... args) dans ce cas, args contient l'argument 3 à arguments.length
Comme déjà mentionné, vous pouvez utiliser le arguments
objet pour récupérer un nombre variable de paramètres de fonction.
Si vous souhaitez appeler une autre fonction avec les mêmes arguments, utilisez apply
. Vous pouvez même ajouter ou supprimer des arguments en les convertissant arguments
en tableau. Par exemple, cette fonction insère du texte avant de se connecter à la console:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Bien que je convienne généralement que l'approche des arguments nommés est utile et flexible (sauf si vous vous souciez de l'ordre, auquel cas les arguments sont les plus faciles), j'ai des inquiétudes concernant le coût de l'approche mbeasley (en utilisant les valeurs par défaut et les extensions). Il s'agit d'un coût extrême à prendre pour extraire les valeurs par défaut. Tout d'abord, les valeurs par défaut sont définies à l'intérieur de la fonction, elles sont donc repeuplées à chaque appel. Deuxièmement, vous pouvez facilement lire les valeurs nommées et définir les valeurs par défaut en même temps en utilisant ||. Il n'est pas nécessaire de créer et de fusionner un autre nouvel objet pour obtenir ces informations.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
C'est à peu près la même quantité de code (peut-être un peu plus), mais devrait représenter une fraction du coût d'exécution.
(parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)
ou pour moins de volume de code, une petite fonction d'assistance comme: function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)
fournir des modèles alternatifs. Cependant, mon argument est toujours valable: créer des objets supplémentaires pour chaque invocation de fonction et exécuter des boucles coûteuses pour définir quelques valeurs par défaut est une quantité folle de surcharge.
Alors que @roufamatic a montré l'utilisation du mot-clé arguments et @Ken a montré un excellent exemple d'un objet à utiliser, je pense que ni vraiment abordé ce qui se passe dans ce cas et peut confondre les futurs lecteurs ou inculquer une mauvaise pratique comme n'indiquant pas explicitement une fonction La méthode / est destinée à prendre une quantité variable d'arguments / paramètres.
function varyArg () {
return arguments[0] + arguments[1];
}
Lorsqu'un autre développeur examine votre code, il est très facile de supposer que cette fonction ne prend pas de paramètres. Surtout si ce développeur n'est pas au courant des arguments mot-clé . Pour cette raison, c'est une bonne idée de suivre une directive de style et d'être cohérent. J'utiliserai Google pour tous les exemples.
Disons explicitement que la même fonction a des paramètres variables:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Il peut y avoir des moments où un objet est nécessaire car c'est la seule méthode recommandée et considérée comme la meilleure pratique d'une carte de données. Les tableaux associatifs sont désapprouvés et découragés.
SIDENOTE: Le mot-clé arguments renvoie en fait un objet en utilisant des nombres comme clé. L'héritage prototypique est également la famille d'objets. Voir la fin de la réponse pour une utilisation correcte de la baie dans JS
Dans ce cas, nous pouvons également le dire explicitement. Remarque: cette convention de dénomination n'est pas fournie par Google mais est un exemple de déclaration explicite du type d'un paramètre. Ceci est important si vous cherchez à créer un modèle typé plus strict dans votre code.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Cela dépend des besoins de votre fonction et de votre programme. Si, par exemple, vous cherchez simplement à renvoyer une base de valeurs sur un processus itératif à travers tous les arguments passés, restez très certainement avec le mot-clé arguments . Si vous avez besoin de définir vos arguments et de mapper les données, la méthode objet est la solution. Regardons deux exemples et nous avons terminé!
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
Comme mentionné en haut de la réponse, le mot-clé arguments renvoie en fait un objet. Pour cette raison, toute méthode que vous souhaitez utiliser pour un tableau devra être appelée. Un exemple de ceci:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
Pour éviter cela, utilisez le paramètre rest:
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Utilisez l' arguments
objet à l'intérieur de la fonction pour avoir accès à tous les arguments transmis.
Sachez que le passage d'un objet avec des propriétés nommées comme l'a suggéré Ken ajoute le coût d'allocation et de libération de l'objet temporaire à chaque appel. Passer des arguments normaux par valeur ou référence sera généralement le plus efficace. Pour de nombreuses applications, les performances ne sont pas critiques, mais pour certaines, elles peuvent l'être.