Quels sont les avantages de l'utilisation d'une fonction anonyme au lieu de fonctions nommées pour les rappels et les paramètres en JavaScript code d'événement?
Je suis nouveau-ish à JavaScript. Je comprends la plupart des concepts de la langue, j'ai été lire sur le prototype de modèle d'héritage, et je suis éveiller mon coup de sifflet, et de plus en plus interactif avant la fin de trucs. C'est intéressant, cette langue, mais je suis toujours un peu éteint par la fonction de rappel spaghetti qui est typique de nombreux non-trivial de modèles d'interaction.
Quelque chose qui a toujours semblé étrange pour moi, c'est que, en dépit de la lisibilité cauchemar qui est un nid de JavaScript imbriqués les rappels, la seule chose que j'ai très rarement l'occasion de voir de nombreux exemples et tutoriels est l'utilisation de modèles prédéfinis nommé fonctions que le rappel des arguments. Je suis un programmeur Java par jour, et jeter le stéréotype de la commission paritaire de recours de l'Entreprise-y les noms des unités de code une des choses que j'ai appris à apprécier sur le travail dans une langue avec une solide sélection de plein de fonctionnalités de l'IDE est que l'utilisation de sens, si longtemps, noms peut faire l'intention et la signification de code beaucoup plus clair, sans le rendre plus difficile d'être réellement productif. Alors pourquoi ne pas utiliser la même approche lors de l'écriture de code JavaScript?
Donner, pensait-elle, je peux venir avec des arguments pour et contre cette idée, mais ma naïveté et de la nouveauté de la langue altère moi de parvenir à une quelconque conclusion quant à pourquoi ce serait une bonne chose au niveau technique.
Pour:
- Flexibilité. Une fonction d'asynchrone avec un rappel paramètre pourrait être atteint par un des nombreux chemins de code et il pourrait être pressés d'avoir à écrire une fonction nommée pour tenir compte de tous les possibles cas de bord.
- Vitesse. Il joue beaucoup dans le profil de hacker. Boulon de choses sur elle jusqu'à ce qu'il fonctionne.
- Tout le monde le fait
- Le fichier de petite taille, même si trivialement, mais chaque geste compte sur le web.
- Plus simple AST? Je suppose que les fonctions anonymes sont générés lors de l'exécution et donc le JIT ne bricolons avec la cartographie du nom d'instructions, mais je suis juste deviner à ce point.
- Plus rapide expédition? Ce n'est pas sûr non plus. Les devinettes de nouveau.
Contre:
- C'est horrible et illisible
- Il ajoute à la confusion lorsque vous êtes imbriquée noix de profondeur dans un marais de rappels (qui, pour être juste, signifie probablement que vous avez écrit, mal construit le code pour commencer avec, mais c'est assez fréquent).
- Pour quelqu'un sans un arrière-plan fonctionnel, il peut être un étrange concept de grok
Avec de nombreux navigateurs modernes montrant la possibilité d'exécuter du code JavaScript beaucoup plus vite qu'avant, je ne suis pas à voir comment tout trivial sorte de gain de performance, on pourrait sortir à l'aide anonyme rappels serait une nécessité. Il semble que, si vous êtes dans une situation où l'utilisation d'un nom de fonction est réalisable (un comportement prévisible et le chemin d'exécution) alors il n'y aurait aucune raison de ne pas.
Alors y at-il des raisons techniques ou des erreurs que je ne suis pas au courant de qui fait de cette pratique si courante pour une raison?
- Je ne suis pas d'accord avec la plupart de vos "pros", on dirait que vous êtes juste deviner. Pas fan de votre cons, soit. Ligne de fond est que de courte fonctions, il est tout simplement plus de sens. Tout comme en Java, nous n'avons pas créer une classe nommée pour faire court, contenues fins, nous utilisons un anonyme intérieur de la classe. JS utilise tout si une variété de module des motifs lors de la complexité des bons de souscription en passant réutilisables et/ou de non-trivial fonctions. Ce est utilisé partout; ne pas avoir vu cela ne veut pas dire qu'il n'est pas utilisé lorsque cela a du sens de le faire.
- Je sais qu'il est là, je suis juste de se demander pourquoi il ne semble pas être la norme, et si il y a n'importe quel objectif, les limitations de la technique: pourquoi c'est le cas. Et comme pour anonymous inner classes en Java, je ne l'ai tendance à utiliser ceux où je n'ai pas besoin de faire une mise en œuvre concrète d'une interface, comme si j'ai besoin de frayer un très simple Exécutable. Et quand je le fais, je n'aime pas ça.
- Dans IE (au moins certaines versions), en utilisant la fonction nommée expressions résultats dans deux fonctions différentes instances (Notez que
var a = function(){...}
est pas un nom de fonction (expression). La fonction attribuée àa
est toujours anonyme). C'est pourquoi il est préférable de les éviter. Bien sûr, vous pouvez toujours utiliser une déclaration de fonction au lieu de cela, mais il me semble inutile de créer un symbole dans le champ d'application si elle n'est utilisée qu'une fois. - cela semble être une bonne, un objectif, une raison technique pour les éviter. Mais qu'en fonction des relevés de déclarations?
- Ce à leur sujet?
- est-ce que IE ont aucun hoquet lorsqu'ils sont nommés dans ce contexte?
- Les déclarations de fonction sont toujours nommés, car ils sont de la forme
function name(){...}
(c'est la déclaration complète, juste après avoirfunction(){...}
est pas valide) et non, il n'y a pas de problèmes autant que je sache. - "Boulon de choses sur elle jusqu'à ce que ça marche" n'est pas un hacker mentalité, c'est un "je ne comprends pas comment mon code fonctionne, c'est toute la magie pour moi" mentalité.
- Je sais qu'ils ont toujours appelé, je me demandais si il y avait un problème technique avec l'aide que comme un mécanisme de dénomination depuis que tu m'as donné une bonne raison d'éviter les expressions de fonction.
- Eh bien, pour moi, ça sonne comme si vous avez une aversion pour les fonctions anonymes/classes en général, sans vraiment fournir une raison technique pour cela. Ils sont tout simplement le bon outil pour un emploi en particulier, et de faire certains types de programmation Java sans eux serait... ridicule.
- Ils ont leur place, je ne suis pas en désaccord avec ça. Mais il y a certainement des endroits où ils PEUVENT être utilisés mais ne sont pas nécessaires et/ou ne sont pas le meilleur ajustement. Il semble pourtant que l'utilisation d'une fonction anonyme est un réflexe en JS. Et vous avez raison, j'ai un peu une aversion pour eux. Et pas pour une raison technique, mais parce que je n'ai pas l'impression qu'ils sont clairs (dans certains contextes). Les fermetures et les fonctions anonymes sont très puissants, mais je vais essayer d'aborder ce à partir d'un lisible par l'homme/droit-outil-pour-le-contexte du poste.
Vous devez vous connecter pour publier un commentaire.
- Je utiliser les fonctions anonymes pour trois raisons:
J'essaie d'éviter la profonde imbrication des fonctions anonymes, parce que cela peut être poilu à comprendre et à lire. Habituellement, lorsque cela se produit, il ya une meilleure façon de structurer le code (parfois avec une boucle, parfois avec une table de données, etc...) et des fonctions nommées n'est habituellement pas la solution non plus.
Je suppose que je devrais ajouter que, si un rappel commence à se faire de plus que d'environ 15 à 20 lignes, et il n'a pas besoin d'un accès direct à des variables dans la portée parent, je serais tenté de lui donner un nom et de le briser dans son propre fonction nommée déclaré ailleurs. Il y a certainement une lisibilité point ici où un non-triviaux de la fonction qui récupère la longue est un peu plus facile à gérer si il est placé dans sa propre unité nommée. Mais, la plupart des rappels, je me retrouve avec ne sont pas longtemps et je le trouve plus lisible pour les garder en ligne.
for
boucle et je ne pense pas qu'unfor
boucle doit être brisé et donné un nom à être lisible.this
pointeur de la fonction d'origine. Vous pouvez la stocker dans une variable locale de la fonction parent (le plus souvent du fait quevar self = this;
et puis vous pouvez accéder àself
dans la fonction anonyme. Très, très pratique.Je préfère fonctions nommées moi-même, mais pour moi ça se résume à une question:
Vais-je utiliser cette fonction n'importe où ailleurs?
Si la réponse est oui, j'ai le nom/définir. Si non, passer comme une fonction anonyme.
Si vous ne l'utilisez une fois, ça n'a pas de sens à la foule l'espace de noms global avec elle. Aujourd'hui, dans un complexe de front-ends, le nombre de fonctions nommées qui aurait pu être anonyme grandit rapidement (facilement plus de 1000 sur vraiment des dessins complexes), résultant en (relativement) gros gains de performances en préférant les fonctions anonymes.
Toutefois, le code de la maintenabilité est aussi extrêmement important. Chaque situation est différente. Si vous n'êtes pas écrire beaucoup de ces fonctions pour commencer, il n'y a pas de mal à le faire de toute façon. C'est vraiment à votre préférence.
Une autre remarque sur les noms. Obtenir dans l'habitude de définir des noms longs va vraiment faire mal la taille de votre fichier. Prenons l'exemple suivant.
Assumer ces deux fonctions font la même chose:
Le second vous indique exactement ce qu'il fait dans le nom. La première est plus ambigu. Cependant, il y a 17 caractères de différence dans le nom. Dire que la fonction est appelé 8 fois dans le code, c'est 153 octets supplémentaires votre code n'a pas besoin d'avoir. Pas colossal, mais si c'est une habitude, l'extrapolation qu'à 10 ou même 100 des fonctions facilement dire quelques KO de différence dans le téléchargement.
De nouveau cependant, la facilité de maintenance doivent être pesés contre les avantages de performance. C'est la douleur de traiter avec un langage de script.
Un peu en retard à la fête, mais certains n'étant pas encore mentionné les aspects des fonctions, anonyme ou le contraire...
Anon funcs ne sont pas facilement visées aux humanoïdes conversations au sujet du code, entre une équipe. E. g., "Joe, pourriez-vous expliquer ce que l'algorithme fait, à l'intérieur de cette fonction. ... Lequel? La 17e fonction anonyme dans le fooApp fonction. ... Non, pas celui-là! Le 17 un!"
Anon funcs sont anonymes pour le débogueur ainsi. (duh!) Par conséquent, le débogueur trace de la pile sera généralement juste montrer un point d'interrogation ou similaires, ce qui rend moins utile lorsque vous avez plusieurs points d'arrêt. Vous frappez le point d'arrêt, mais trouver vous-même le défilement de la fenêtre de débogage vers le haut/vers le bas pour trouver d'où l'enfer vous êtes dans votre programme, parce que hey, le point d'interrogation de la fonction juste ne pas le faire!
Des préoccupations au sujet de polluer l'espace de noms global sont valables, mais il est facile de remédier par de nommage de vos fonctions en tant que nœuds au sein de votre propre objet racine, comme "myFooApp.happyFunc = fonction ( ... ) { ... }; ".
Fonctions qui sont disponibles dans l'espace de noms global, ou comme des nœuds dans la racine de votre objet, comme ci-dessus, peut être invoqué à partir du débogueur directement, au cours du développement et de débogage. E. g., au niveau de la console de ligne de commande, faire "myFooApp.happyFunc(42)". C'est un outil extrêmement puissant de la compétence qui n'existe pas (natif) dans compilé les langages de programmation. Essayez ça avec un anon func.
Anon funcs peut être rendu plus lisible par les assigner à une variable, puis en passant le var comme le rappel (au lieu de inlining). E. g.:
var funky = fonction ( ... ) { ... };
jQuery('#otis).cliquez sur(funky);
À l'aide de l'approche ci-dessus, vous pourriez potentiellement groupe de plusieurs anon funcs au sommet de l'autorité parentale, func, puis en dessous, de la viande d'instructions séquentielles devient beaucoup plus regroupés, et plus facile à lire.
Bien, juste pour être clair, pour le bien de mes arguments, les suivantes sont des fonctions anonymes/les expressions de fonction dans mon livre:
Pour:
Il peut réduire un peu de trucs, en particulier dans les fonctions récursives (où l'on pourrait (devrait en fait depuis des arguments.le destinataire de l'appel est déconseillée) toujours utiliser un nom de référence par le dernier exemple en interne), et il est clair que la fonction n'a jamais un feu dans un seul endroit.
Code de la lisibilité gagner: dans l'exemple de l'objet littéral avec anon funcs affecté en tant que méthodes, il serait idiot d'ajouter plus d'endroits pour la chasse et de picorer pour la logique dans votre code lorsque le point de l'ensemble de l'objet littéral est à plop certaines fonctionnalités connexes dans le même idéalement référencé spot. Lors de la déclaration de méthodes publiques dans un constructeur, cependant, j'ai tendance à définir marqué les fonctions inline et puis assigner comme les références de ce.sameFuncName. Il me permet d'utiliser les mêmes méthodes en interne sans le " cela.' trucs et rend ordre de définition d'un non-préoccupation quand ils s'appellent les uns les autres.
Utile pour éviter inutile espace de noms global de la pollution interne des espaces de noms, cependant, ne devrait jamais être largement rempli ou manipulé par plusieurs équipes simultanément, de sorte que cet argument semble un peu ridicule à moi.
Je suis d'accord avec la ligne de rappels lors de la configuration de court gestionnaires d'événements. C'est ridicule d'avoir à chasser pour un 1-5 ligne de la fonction, en particulier depuis avec JS et la fonction de levage, les définitions pourrait se retrouver n'importe où, même pas dans le même fichier. Cela peut arriver par accident, sans rien casser et non, vous n'avez pas toujours avoir le contrôle de ce genre de choses. Les événements se soldent toujours par une fonction de rappel de feu. Il n'y a pas de raison d'ajouter des liens à la chaîne de noms que vous avez besoin de numériser à travers juste pour désosser simple événement-les gestionnaires d'une grande base de code et la trace de la pile problème peut être résolu par l'abstraction des déclencheurs d'événements eux-mêmes méthodes que le journal des infos utiles lorsque le mode debug est activé et le feu se déclenche. Je suis en train de commencer à construire ensemble des interfaces de cette façon.
Utile lorsque vous SOUHAITEZ que la commande de définition de la fonction à la matière. Parfois, vous voulez être certain d'une fonction par défaut est ce que vous pensez qu'il est jusqu'à un certain point dans le code où il est bon de le redéfinir. Ou vous voulez la rupture à être plus évidente lorsque les dépendances obtenir mélangées.
Contre:
Anon ne pouvez pas profiter de la fonction de levage. C'est une différence majeure. J'ai tendance à prendre de lourdes avantage de levage à définir mon propre explicitement nommé funcs et l'objet des constructeurs vers le bas et d'obtenir à la définition de l'objet et de la main-type de la boucle des trucs à droite jusqu'au sommet. Je trouve qu'il rend le code plus facile à lire quand vous le nom de votre vars bien et obtenir une vue d'ensemble de ce qu'il se passe avant de ctrl-Fing pour plus de détails, seulement quand ils ont une importance pour vous. De levage peut également être un avantage énorme fortement événementiel d'interfaces où imposant un ordre strict de ce qui est disponible quand peut vous mordre dans le cul. De levage a ses propres mises en garde (comme la circulaire de potentiel de référence), mais c'est un outil très utile pour organiser et rendre le code lisible lorsque utilisé droite.
Lisibilité/Debug. Absolument, il s'habitue trop fortement à la fois, et il peut faire le débogage et le code de la lisibilité d'une dispute. Des bases de codes qui dépendent fortement de JQ, par exemple, peut être un grave PITA à lire et à déboguer si vous n'avez pas encapsuler la quasi-inévitable anon-lourds et massivement surchargé args de l' $ soupe dans une manière sensible. JQuery passez méthode, par exemple, est un exemple classique de l'utilisation excessive de l'anon funcs lorsque vous déposez deux anon funcs en elle, car il est facile pour un débutant de supposer que c'est un standard de l'écouteur d'événement d'attribution de méthode plutôt que d'une méthode surchargée pour affecter des gestionnaires pour un ou deux événements.
$(this).hover(onMouseOver, onMouseOut)
est beaucoup plus clair que les deux anon funcs.Ses plus lisible à l'aide des fonctions nommées et ils sont également capables d'auto-référencement, comme dans l'exemple ci-dessous.
http://jsfiddle.net/Yq2WD/
C'est agréable quand vous voulez avoir un immédiatement appelé la fonction qui fait référence à elle-même, mais ne pas ajouter à l'espace de noms global. Il est toujours lisible, mais ne pas polluer. Avoir votre gâteau et le manger à.
Salut, mon nom est Jason OU salut, mon nom est ???? vous chercher.