Je trouve la fonctionnalité des paramètres nommés en C # très utile dans certains cas.
calculateBMI(70, height: 175);
Que puis-je utiliser si je le souhaite en JavaScript?
Ce que je ne veux pas, c'est ceci:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
Cette approche que j'ai déjà utilisée. Y a-t-il un autre moyen?
Je peux utiliser n'importe quelle bibliothèque pour ce faire.
javascript
function
optional-parameters
named-parameters
Robin Maben
la source
la source
Function
en javascript peut faire.Function
en Javascript ne peut pas changer la syntaxe de base de JavascriptcalculateBMI(70, /*height:*/ 175);
, (2) fournir un objetcalculateBMI(70, {height: 175})
, ou (3) utiliser une constanteconst height = 175; calculateBMI(70, height);
.Réponses:
ES2015 et versions ultérieures
Dans ES2015, la déstructuration des paramètres peut être utilisée pour simuler des paramètres nommés. Il faudrait que l'appelant passe un objet, mais vous pouvez éviter toutes les vérifications à l'intérieur de la fonction si vous utilisez également des paramètres par défaut:
ES5
Il existe un moyen de se rapprocher de ce que vous voulez, mais il est basé sur la sortie de
Function.prototype.toString
[ES5] , qui dépend dans une certaine mesure de l'implémentation, de sorte qu'il peut ne pas être compatible avec plusieurs navigateurs.L'idée est d'analyser les noms de paramètres à partir de la représentation sous forme de chaîne de la fonction afin de pouvoir associer les propriétés d'un objet au paramètre correspondant.
Un appel de fonction pourrait alors ressembler à
où
a
etb
sont des arguments positionnels et le dernier argument est un objet avec des arguments nommés.Par exemple:
Que vous utiliseriez comme:
DEMO
Il y a quelques inconvénients à cette approche (vous avez été prévenu!):
undefined
(ce qui est différent de n'avoir aucune valeur). Cela signifie que vous ne pouvez pas utiliserarguments.length
pour tester le nombre d'arguments transmis.Au lieu d'avoir une fonction créant le wrapper, vous pouvez également avoir une fonction qui accepte une fonction et diverses valeurs comme arguments, telles que
ou même étendre
Function.prototype
pour que vous puissiez faire:la source
Object.defineProperty
et ensembleenumerable
pourfalse
). Il faut toujours être prudent lors de l'extension des objets natifs. L'approche globale semble un peu hacky, donc je ne m'attendrais pas à ce que cela fonctionne maintenant et pour toujours;)undefined
«aucune valeur», on peut ajouter que c'est exactement ainsi que fonctionnent les valeurs par défaut des fonctions JS - en les traitantundefined
comme une valeur manquante.Non - l'approche objet est la réponse de JavaScript à cela. Cela ne pose aucun problème à condition que votre fonction attend un objet plutôt que des paramètres séparés.
la source
Ce problème est une bête noire depuis un certain temps. Je suis un programmeur chevronné avec de nombreuses langues à mon actif. L'une de mes langues préférées que j'ai eu le plaisir d'utiliser est Python. Python prend en charge les paramètres nommés sans aucune astuce .... Depuis que j'ai commencé à utiliser Python (il y a quelque temps), tout est devenu plus facile. Je crois que chaque langue devrait prendre en charge les paramètres nommés, mais ce n'est tout simplement pas le cas.
Beaucoup de gens disent d'utiliser simplement l'astuce "Passer un objet" pour que vous ayez nommé des paramètres.
Et cela fonctionne très bien, sauf ..... en ce qui concerne la plupart des IDE, beaucoup d'entre nous, développeurs, s'appuient sur des indices de type / argument dans notre IDE. J'utilise personnellement PHP Storm (avec d'autres IDE JetBrains comme PyCharm pour python et AppCode pour Objective C)
Et le plus gros problème avec l'utilisation de l'astuce "Passer un objet" est que lorsque vous appelez la fonction, l'EDI vous donne un indice de type unique et c'est tout ... Comment sommes-nous censés savoir quels paramètres et types doivent entrer dans le objet arg1?
Donc ... l'astuce "Passer un objet" ne fonctionne pas pour moi ... Cela provoque en fait plus de maux de tête lorsque je regarde le docblock de chaque fonction avant de savoir quels paramètres la fonction attend .... Bien sûr, c'est génial pour lorsque vous maintenez le code existant, mais c'est horrible pour écrire du nouveau code.
Eh bien, c'est la technique que j'utilise .... Maintenant, il peut y avoir des problèmes avec cela, et certains développeurs peuvent me dire que je le fais mal, et j'ai un esprit ouvert quand il s'agit de ces choses ... Je suis toujours prêt à chercher de meilleures façons d'accomplir une tâche ... Donc, s'il y a un problème avec cette technique, alors les commentaires sont les bienvenus.
De cette façon, j'ai le meilleur des deux mondes ... le nouveau code est facile à écrire car mon IDE me donne tous les conseils d'argument appropriés ... Et, tout en conservant le code plus tard, je peux voir en un coup d'œil, non seulement le valeur passée à la fonction, mais aussi le nom de l'argument. La seule surcharge que je vois est de déclarer vos noms d'argument en tant que variables locales pour éviter de polluer l'espace de noms global. Bien sûr, c'est un peu de frappe supplémentaire, mais trivial par rapport au temps qu'il faut pour rechercher des docblocks lors de l'écriture de nouveau code ou de la maintenance du code existant.
la source
myFunc(/*arg1*/ 'Param1', /*arg2*/ 'Param2');
c'est mieux quemyFunc(arg1='Param1', arg2='Param2');
, parce que cela n'a aucune chance de tromper le lecteur que tous les arguments nommés réels se produisentSi vous voulez préciser ce que sont chacun des paramètres, plutôt que d'appeler simplement
pourquoi ne pas faire ce qui suit
Bien sûr, c'est une ligne de code supplémentaire, mais elle gagne en lisibilité.
la source
someFunction(height: 115);
mais si vous écrivez,someFunction(height);
vous définissez en fait la largeur.someFunction(width = 70, height = 115);
. Les variables sont déclarées en haut de l'étendue actuelle dans le code JavaScript généré.Une autre façon serait d'utiliser les attributs d'un objet approprié, par exemple comme ceci:
Bien sûr, pour cet exemple composé, il est quelque peu dénué de sens. Mais dans les cas où la fonction ressemble
cela pourrait être plus utile. Il pourrait également être combiné avec l'idée "parameterfy" pour créer un tel objet à partir d'une fonction existante de manière générique. C'est-à-dire que pour chaque paramètre, il créerait un membre pouvant évaluer une version partiellement évaluée de la fonction.
Cette idée est bien sûr liée à Schönfinkeling alias Currying.
la source
Il y a une autre manière. Si vous passez un objet par référence, les propriétés de cet objet apparaîtront dans la portée locale de la fonction. Je sais que cela fonctionne pour Safari (je n'ai pas vérifié les autres navigateurs) et je ne sais pas si cette fonctionnalité a un nom, mais l'exemple ci-dessous illustre son utilisation.
Bien que dans la pratique, je ne pense pas que cela offre une valeur fonctionnelle au-delà de la technique que vous utilisez déjà, c'est un peu plus propre sémantiquement. Et cela nécessite toujours de passer une référence d'objet ou un objet littéral.
la source
En essayant Node-6.4.0 (process.versions.v8 = '5.0.71.60') et Node Chakracore-v7.0.0-pre8 puis Chrome-52 (V8 = 5.2.361.49), j'ai remarqué que les paramètres nommés sont presque mis en œuvre, mais cet ordre a toujours préséance. Je ne trouve pas ce que dit la norme ECMA.
Mais l'ordre est requis !! Est-ce le comportement standard?
la source
b=10
expression est10
, et c'est ce qui est transmis à la fonction.f(bla=10)
fonctionnerait également (il affecte 10 à la variablebla
et transmet ensuite la valeur à la fonction).a
etb
dans la portée globale comme effet secondaire.Fonction d'appel
f
avec des paramètres nommés passés en tant qu'objetappelle essentiellement sa composition
f(...g(o))
où j'utilise la syntaxe de propagation etg
est une carte "contraignante" reliant les valeurs des objets à leurs positions de paramètres.La carte de liaison est précisément l'ingrédient manquant, qui peut être représenté par le tableau de ses clés:
Notez les trois ingrédients découplés: la fonction, l'objet avec des arguments nommés et la liaison. Ce découplage permet une grande souplesse d'utilisation de cette construction, où la liaison peut être arbitrairement personnalisée dans la définition de la fonction et arbitrairement étendue au moment de l'appel de la fonction.
Par exemple, vous voudrez peut-être abréger
height
et auwidth
furh
etw
à mesure de la définition de votre fonction, pour la rendre plus courte et plus propre, tandis que vous voulez toujours l'appeler avec des noms complets pour plus de clarté:Cette flexibilité est également plus utile pour la programmation fonctionnelle, où les fonctions peuvent être arbitrairement transformées avec leur nom de paramètre d'origine perdu.
la source
Venant de Python, cela m'a dérangé. J'ai écrit un wrapper / Proxy simple pour le nœud qui acceptera les objets positionnels et les mots clés.
https://github.com/vinces1979/node-def/blob/master/README.md
la source
f(x, opt)
oùopt
est un objet. Que cela aide à éviter ou à créer des erreurs (comme celles causées par une faute d'orthographe et la difficulté de se souvenir des noms de mots clés) reste une question.kwargs
dict un par un et enfin lever unTypeError
s'il reste des clés inconnues). Votref(x, opt)
solution permet à laf
fonction de faire quelque chose comme dans Python 2, mais vous devez gérer vous-même toutes les valeurs par défaut.f(x, opt)
fonctionne déjà, alors que je ne vois pas comment cela aide à répondre à la question, où par exemple vous voulez faire les deuxrequest(url)
etrequest({url: url})
cela ne serait pas possible en créanturl
un paramètre uniquement par mot-clé.Contrairement à ce que l'on croit généralement, les paramètres nommés peuvent être implémentés en JavaScript standard à l'ancienne (pour les paramètres booléens uniquement) au moyen d'une convention de codage simple et soignée, comme illustré ci-dessous.
Avertissements:
L'ordre des arguments doit être conservé - mais le modèle est toujours utile, car il rend évident quel argument réel est destiné à quel paramètre formel sans avoir à chercher la signature de la fonction ou à utiliser un IDE.
Cela ne fonctionne que pour les booléens. Cependant, je suis sûr qu'un modèle similaire pourrait être développé pour d'autres types en utilisant la sémantique de coercition de type unique de JavaScript.
la source
height
par le nom quel que soit l'ordre param.