11
votes

Création d'un plug-in JQuery: Meilleures pratiques concernant la visibilité des fonctions?

Je crée un plugin JQuery. Jusqu'à présent, ça marche bien, mais je doute de la façon dont je fais des choses: xxx

J'utilise MyScope pour stocker toutes mes fonctions "privées". Je ne veux pas que l'utilisateur puisse aller $ ("p"). Dosomething () , mais je dois les utiliser.

Je pourrais tout déplacer La fonction myMETHOD , mais cela créerait une fonction longue de 100 lignes et les gens me détesteraient pour cela.

Quelles sont les meilleures pratiques dans cette situation? Y a-t-il de superbes tutoriels là-bas à ce sujet?


1 commentaires

Juste quelque chose à noter, toute la bibliothèque de jQuery est en une seule fonction, c'est une méthode de scopage parfaitement légitime, lorsque vous avez besoin d'une fermeture, utilisez une fermeture :)


3 Réponses :


18
votes

Vous pouvez encapsuler vos fonctions pour faire ce que vous voulez, comme celui-ci: xxx

Vous pouvez afficher une démo rapide ici

"Je pourrais tout déplacer dans la fonction MyMethod, mais cela créerait une fonction longue de 100 lignes et les gens me détestent pour cela." .... pourquoi?

Le code doit être défini quelque part, si vous ne voulez pas qu'il soit accessible de manière externe, il y a quelques façons, mais je ne le fais pas Découvrez pourquoi quiconque voudrait vous aimer faire exactement cela. Tout est question de portée et d'où vous voulez des choses, tant que vous ne le déclarez pas plusieurs fois et n'exposant que ce que vous voulez, je ne vois aucun problème.

Il y a plusieurs styles à la déclarer , certains avec le même effet, l'option que j'ai donnée est l'une des nombreuses, mais en plaçant des choses à l'intérieur de MyMethod est une approche parfaitement raisonnable.


être plus complet, < un href = "http://jsfiddle.net/ccxmm/1/" rel = "noreferrer"> Voici une autre alternative : xxx

ou un autre : xxx


articles connexes:


20 commentaires

@nick: Avoir une seule fonction énorme et une réutilisation 0 du code est assez mauvais IMHO. Surtout depuis que j'appelle DosomeLeelse () dans 3 ou 4 endroits différents de Dosomething ().


@margrargg: Votre exemple ne montre pas que ... vous devriez donner plus d'indices sur votre utilisation si c'est le cas, même allusion Celles-ci seront utilisées pour plusieurs plugins être un début.


@MarCgg: Cela aiderait à obtenir une meilleure réponse :) ... une méthode de plug-in est la norme, de multiples méthodes n'est pas, sans aucune autre astuce, les gens assumeront ce que vous faites correspondre à la majorité des cas.


@MarCgg: Votre exemple mis à jour est toujours convivial, par exemple: jsfiddle.net/ccxmm Vous ne déclarez aucun Code deux fois, sauf si je suis toujours mal compris votre plugin global?


@nick: Tout placer dans MyMethod () n'impliquera pas que les fonctions seront redéfinies à chaque fois que le $ (). MyMethod () est appelé? Parce que si c'est que je suis un peu inquiet pour les performances


@nick ouais le code que vous avez mis sur le violon fonctionnerait! (merci ^^) Je suis juste inquiet un peu de spectacles


@MarCgg: Nope Ce ne sera pas ... Vous ne redéfinissez pas la fonction, vous ne faites que passer une valeur dans et que vous faites quelque chose avec elle (dans ce cas, vous utilisez ce au lieu d'une valeur, mais pas de différence). Aucune copie de la fonction n'est faite, elle est réutilisée comme elle devrait être. J'avais cumulé la discussion de fermeture ici: Stackoverflow .com / questions / 111102 / ...


@NICK: Ce que je veux dire, c'est que, puisque la définition de dosomething est à MyMethod, il me semble que chaque fois que j'appelle MyMethod, il redéfinira la réduction des performances réduisant dossé par rapport à une solution comme une solution telle que Time Down ... N'est-ce pas?


@MarCgg - Je ne suis pas sûr de savoir comment expliquer cela clairement ... Lorsque vous appelez une fonction, vous ne faites pas de copie, vous passez simplement. Si une fonction avait des variables internes susceptibles de changer par exécution de la fonction que vous auriez besoin d'une "copie", mais depuis le filetage unique de JavaScript, il n'est pas nécessaire de le faire. N'oubliez pas non plus que dans tous les navigateurs modernes, votre code sera optimisé, bien au-delà de ce que vous pouvez faire dans le JS de toute façon.


Nick, Marcgg a raison: vous obtiendrez un nouvel objet de fonction pour DOSOMOD "/ code> chaque fois que myMethod est exécuté.


Aha, qui a raison? Je viens de lire que "une fermeture est un cadre de pile qui n'est pas distribué quand la fonction renvoie" alors cela me fait un peu pense que @Nick a raison, mais @ totim me fait douter


C'est facile à vérifier. var f = fonction () {fonction g () {}; retour g; }; var g1 = f (), g2 = f (); ALERTE (G1 === G2); Si Nick a raison, vous vous attendez à true , si je suis correct, vous attendez false . Devinez quoi c'est :)


@Tim Down: Dans ce cas, vous le retournez à l'extérieur de la fermeture, c'est bien sûr que cela aurait besoin d'une copie à chaque fois pour l'exposer, je ne suis pas sûr que c'est un test valide du tout. Pour être clair, ne pas dire que vous avez tort, il suffit de dire que le test n'est pas un moyen valide de le déterminer.


@margrargg: Je ne peux pas penser à un moyen valide de tester cela, mais encore une fois, je ne pense pas que ça compte ... Ceci sera optimisé par le navigateur d'une autre manière (les moteurs de traçage font incroyable Montants d'optimisation sous les couvertures). @Tim peut avoir raison en termes de ce que devrait-il utiliser d'être sûr d'utiliser les 2 autres approches que j'ai ajoutées à la réponse ... Mais ce que la spécification dit se produit et ce qui arrive réellement d'un point de vue de la performance (Pendant qu'il est toujours se comporter comme la spécification) sont deux choses différentes, en soyez conscient de cela.


Nick: En fait, j'aurais peut-être commencé avec la spécification Ecmascript 3, en particulier l'article 10 sur les contextes d'exécution. Certaines phrases de choix: "Chaque appel de la fonction et du constructeur entre dans un nouveau contexte d'exécution" (section 10.2), qui implique de passer par la phase d'instanciation variable. Dans le cadre de celui-ci, "pour chaque fonctionnement de la fonction dans le code, dans la commande de texte source, créez une propriété de l'objet de variable dont le nom est l'identifiant de la fonction de fonctionnement, dont la valeur est le résultat renvoyé en créant un objet de fonction comme décrit dans 13" (à partir de la section 10.1.3).


@IM: Reportez-vous à mon commentaire précédent :) Je ne suis pas en désaccord avec la spécification, je dis ce qui se fait entrer, tracé et optimisé en faisant une non-question, mais pas dans les navigateurs plus anciens.


J'ai vu votre commentaire avant de poster le mien mais j'étais jusqu'à présent dans ma pédanterie Spec, je ne pouvais pas éventuellement arrêter :) Vous pourriez bien avoir raison de pouvoir être optimisé par le navigateur, et cela risque de ne pas avoir d'importance à autre chose que une grande échelle, mais cela vaut toujours la peine de savoir.


@TIM - Enttement d'accord, et en utilisant l'une des autres méthodes ajoutées garantit qu'il s'agit d'une non-question dans tous les cas, des notes définitivement utiles tout autour.


Ok alors ... quelle réponse accepter ^^? Je suppose que Nick est depuis que c'est le plus avancé et avec beaucoup de cas différents. Si vous pouviez simplement ajouter une certaine référence à ce que nous avons dit dans les commentaires + liens et que ce serait une entrée assez cool. J'ai certainement appris beaucoup


Dessinez l'attention des gens sur cette réponse est probablement plus utile que de les dessiner à la mienne à cause de la discussion, alors je dirais celui-ci. Dommage qu'il n'y ait pas de points pour les aides :)



4
votes

Je mettrais tout à l'intérieur de la fonction JQuery.fn.MymeThod, pour éviter des collisions d'espace de noms éventuelles et créer un code de nettoyage. Ce motif vous permet également de faire des méthodes privées qui ne sont pas accessibles de l'extérieur de la fonction MyMethod. XXX


7 commentaires

C'est assez intéressant, savez-vous si c'est une pratique courante?


Quel est le point de que ? Vous pouvez utiliser des variables locales au lieu d'un objet avec des propriétés.


Je pense que oui, au moins parmi mes collègues et moi, j'ai vu beaucoup de plugins jQuery écrites de cette façon, ou d'au moins une variation de cela.


Le point de "cet" objet est d'éviter des collisions d'espace de noms possibles. Par exemple, si je venais d'appeler mes méthodes init (), Dosomething () et DosomseLeelse (), je risque d'appeler accidentellement une fonction globale par le même nom. Bien que cela soit improbable, il reste encore une chose à craindre. De plus, vous pouvez transmettre le "cet" objet pour rappeler des méthodes, leur donnant accès à la portée actuelle.


@ harold1983: n'importe quel exemple de là-bas?


@ Harold1983-: tandis que la chose mondiale est vraie, vous utiliseriez la référence locale-est ... I Complètement D'accord C'est la meilleure pratique d'éviter cela, mais ce ne serait pas un problème , du moins pas en tout cas, je peux penser.


Harold: OK, ces points sont valables en général, mais ne s'appliquent pas à cet exemple. Assez juste.



6
votes

Il n'y a rien de mal à utiliser une grande fonction juste pour créer une nouvelle portée. Ce qui suit conserve DOSOMODIAT et DOSOMODORELSE PRIVÉE ET Évite la définition de nouveaux DOSOMOD "/ code> et DOSOMODORELSE Fonctions pour chaque invocation de MyMethod , ce qui se produirait si vous mettrez dosshant et dosomoqLeLse inside myMETHOD de la définition de MyMethod xxx


5 commentaires

Désolé mais je ne suis pas sûr de ce que vous essayez de faire ici. Pourriez-vous donner un exemple de comment cela serait utilisé?


Le point est que DOSOMODIAT et DOSOMODORELSE ne sont accessibles que dans la fonction enfermante, pas à l'extérieur. L'exemple est l'appel à dosomething (this.id); dans la définition de jquery.fn.mymethod . Garder le Dosomething et DOSOMODORELSE Les fonctions d'être accessibles à un autre code sont ce que je voulais vouloir vouloir et c'est ce que cela atteint. Ai-je mal compris la question?


@tim: C'est assez cool, merci! Je ne connais pas vraiment cela (fonction () {}) (); Syntaxe, y a-t-il une documentation sur ce que cela fera?


@MarCgg: blog.morrisjohns.com/javascript_closures_for_dummies.html Aucune infraction signifiée par le nom, mais C'est une bonne référence d'apprentissage de la fermeture.


Marcgg: Il est communément appelé motif de module. Si vous faites votre Google, il y a beaucoup de références. Celui-ci semble raisonnable: Adéquativementgood.com/2010/3/javascript -Modile-motif-in-profondeur