Welche Vorteile bietet die Verwendung anonymer Funktionen anstelle von benannten Funktionen für Callbacks und Parameter im JavaScript-Ereigniscode?
Ich bin neu-isch zu JavaScript. Ich verstehe viele der Konzepte der Sprache, die ich gelesen habe bis auf die prototype-Vererbung-Modell, und ich bin bekommen meine Pfeife mit mehr und mehr interaktive front-end-Zeug. Es ist eine interessante Sprache, aber ich bin immer ein wenig deaktiviert ist, indem Sie die callback-spaghetti, die typisch für viele nicht-triviale Interaktion Modelle.
Etwas, das hat immer schien mir seltsam ist, dass trotz der besseren Lesbarkeit Alptraum, das ist ein nest von JavaScript verschachtelte callbacks, die eine Sache, die ich sehr selten sehe, in viele Beispiele und tutorials ist der Einsatz von vordefinierten Funktionen als callback-Argumente. Ich bin ein Java-Programmierer bei Tag, und verwerfen die stereotype jabs über Enterprise-y Namen für Einheiten von code eines der Dinge, die ich bin gekommen, um zu genießen, zum arbeiten in einer Sprache, mit einer starken Auswahl an ausgereifter IDE ist, dass die Verwendung sinnvoll, wenn lange Namen machen können, der Absicht und Bedeutung der code viel übersichtlicher, ohne dass es mehr schwierig, wirklich produktiv zu sein. Also warum nicht verwenden Sie den gleichen Ansatz beim schreiben von JavaScript-code?
Gibt es Gedanken, die ich kann kommen mit Argumenten, sowohl für als auch gegen diese Idee, aber meine Naivität und Neuheit der Sprache beeinträchtigt mich nicht erreichen irgendwelche Schlussfolgerungen zu ziehen, warum, das wäre gut auf der technischen Ebene.
Vorteile:
- Flexibilität. Eine asynchrone Funktion mit einem callback-parameter könnte erreicht werden durch eine von vielen verschiedenen code-Pfade und es könnte sein, gehetzt zu haben, um schreiben Sie eine benannte Funktion zu berücksichtigen, für jedes einzelne mögliche edge-Fall.
- Geschwindigkeit. Es spielt stark in der hacker-Mentalität. Bolt Dingen auf, bis es klappt.
- Alle anderen tun es
- Kleinere Dateigrößen, auch wenn so trivial, aber jedes bisschen zählt im web.
- Einfacher AST? Ich würde davon ausgehen, dass anonyme Funktionen werden zur Laufzeit generiert und damit der JIT nicht der dreck über die mit der Zuordnung der Namen zu den Anweisungen, aber ich kann nur raten an dieser Stelle.
- Schneller Versand? Nicht sicher, über diese ein. Raten wieder.
Nachteile:
- Es ist scheußlich und unleserlich
- Er fügt zur Verwirrung, wenn Sie verschachtelt sind Nüsse tief in einem Sumpf von Rückrufen (die, um fair zu sein, bedeutet wohl, Sie schreiben schlecht konstruierten code, um mit zu beginnen, aber es ist durchaus üblich).
- Für jemand ohne funktionalen hintergrund kann es eine bizarre Konzept zu grok
Mit so vielen modernen Browsern zeigt die Fähigkeit zum ausführen von JavaScript-code deutlich schneller als vorher, ich bin andernfalls zu sehen, wie irgendwelche belanglosen Art der performance-Gewinn könnte man mit anonymen Rückrufe wäre eine Notwendigkeit. Es scheint, dass, wenn Sie in einer situation, wo Sie eine benannte Funktion machbar ist (vorhersagbares Verhalten und den Pfad der Ausführung), dann gäbe es keinen Grund, nicht zu.
Gibt es irgendwelche technischen Gründe oder fallen, ich bin mir nicht bewusst, das macht diese Praxis so alltäglich für einen Grund?
InformationsquelleAutor der Frage Doug Stephen | 2012-04-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich nutze anonyme Funktionen aus drei Gründen:
Ich versuche zu vermeiden, die Tiefe der Schachtelung von anonymen Funktionen, da kann sein haarige zu verstehen und zu Lesen. In der Regel, wenn das passiert, gibt es einen besseren Weg, um die Struktur des Codes (manchmal mit einer Schleife, manchmal mit einer Daten-Tabelle, etc...) und der genannten Funktionen ist in der Regel nicht die Lösung gibt.
Ich glaube, ich würde hinzufügen, dass, wenn ein Rückruf gestartet, um mehr als 15 bis 20 Zeilen lang und es braucht nicht den direkten Zugriff auf die Variablen im übergeordneten Bereich, ich würde versucht sein, geben Sie einen Namen ein und brechen es in seine eigene benannte Funktion deklariert anderswo. Es ist definitiv eine Lesbarkeit Punkt hier, wo Sie eine nicht-triviale Funktion, wird lange nur mehr wartbar, wenn es in seine eigene benannte Einheit. Aber die meisten Rückrufe habe ich am Ende nicht, dass lange, und ich finde es besser lesbar zu halten, Sie inline.
InformationsquelleAutor der Antwort jfriend00
Ich lieber benannten Funktionen mich, aber für mich kommt es auf die eine Frage:
Werde ich diese Funktion irgendwo anders?
Wenn die Antwort ja ist, ich name/definieren. Wenn nicht, übergeben Sie es als eine anonyme Funktion.
Wenn Sie es nur einmal, es macht keinen Sinn, drängen sich die globalen namespace. In der heutigen komplexen front-ends, die Anzahl der benannten Funktionen, die hätte anonym wächst schnell (Locker über 1000 auf wirklich komplizierte designs), die sich in (relativ) große performance-Gewinne durch Bevorzugung anonyme Funktionen.
Jedoch code-Wartbarkeit ist auch extrem wichtig. Jede situation ist anders. Wenn Sie nicht schreiben Sie eine Menge von diesen Funktionen zu beginnen mit, es gibt keinen Schaden, es zu tun, so oder so. Es ist wirklich bis zu Ihrer Präferenz.
Eine weitere Anmerkung zum Namen. Immer in der Gewohnheit der Festlegung langen Namen wird wirklich verletzt, Ihre Dateigröße. Nehmen Sie das folgende Beispiel.
Übernehmen beide Funktionen das gleiche tun:
Der zweite sagt Ihnen genau, was Sie tut im Namen. Die erste ist mehr als zweideutig. Jedoch, es sind 17 Zeichen von Differenz in den Namen. Sagen die Funktion aufgerufen wird 8 mal den ganzen code, ist 153 zusätzliche bytes Ihren code nicht brauchen, um haben. Nicht riesig, aber wenn es zur Gewohnheit wird, rechnet man, dass bis 10 s oder auch 100s von Funktionen wird einfach bedeuten, ein paar KB Unterschied im download.
Jedoch wieder, Wartbarkeit muss abgewogen werden gegen den nutzen der Leistung. Dies ist der Schmerz, der sich mit einer Programmiersprache.
InformationsquelleAutor der Antwort Andrew Ensley
Gut, nur klar zu sein, wegen meiner Argumente, die folgenden sind alle anonyme Funktionen/Funktion Ausdrücken in meinem Buch:
Vorteile:
Kann es zu reduzieren ein wenig Reste, insbesondere in rekursiven Funktionen (wo man konnte (sollte eigentlich, da Argumente.angerufene ist veraltet) noch die Verwendung einer benannten Referenz pro das Letzte Beispiel intern) und verdeutlicht die Funktion immer nur Brände in diesem einem Ort.
Lesbarkeit der Codes gewinnen: am Beispiel der Objekt-literal mit anon funcs zugeordnet, da die Methoden, es würde albern sein, um hinzuzufügen mehr Plätze für die Jagd und picken für die Logik in deinem code wird die ganze Sache, die Objekt-literal ist plop einige zusammenhängende Funktionalitäten in die gleiche bequem referenzierten Stelle. Bei der Deklaration von public-Methoden in einem Konstruktor, aber ich dazu neigen, zu definieren, beschriftet inline-Funktionen und weisen Sie dann als Verweise auf diese.sameFuncName. Es lässt mich mit den gleichen Methoden intern, ohne den '.' cruft ' und macht, um der definition eine nicht-Sorge, wenn Sie einander anrufen.
Nützlich für die Vermeidung von unnötig globalen namespace-Verschmutzung - internen namespaces, jedoch sollten nicht immer sein, dass weitgehend gefüllt oder behandelt werden, die von mehreren teams gleichzeitig, so dass argument scheint ein wenig albern für mich.
Stimme ich mit der inline-Rückrufe auf, wenn die Einstellung kurzes event-Handler. Es ist dumm, um auf die Jagd nach einem 1-5-line-Funktion, vor allem, da mit JS und Funktion hochziehen, die Definitionen könnten überall landen, auch nicht innerhalb der gleichen Datei. Dies könnte geschehen durch Zufall, ohne etwas zu zerbrechen und Nein, Sie haben nicht immer die Kontrolle über das Zeug. Ereignisse immer in eine callback-Funktion ausgelöst wird. Es gibt keinen Grund, weitere Verknüpfungen hinzufügen, um die Kette der Namen, die Sie Scannen müssen nur durch reverse Engineering einfachen event-Handler in einer großen Codebasis und der stack-trace Anliegen können angesprochen werden-durch die Abstraktion Ereignis löst sich in Methoden, die log nützliche Informationen, wenn Sie den debug-Modus eingeschaltet und die Trigger auslösen. Ich bin eigentlich anfangen zu bauen gesamte Oberfläche diese Art und Weise.
Nützlich, wenn Sie WOLLEN, die Reihenfolge der definition einer Funktion, egal. Manchmal möchten Sie sicher sein, eine Standard-Funktion ist, was Sie denken, es ist bis zu einem bestimmten Punkt im code, wo es okay ist, neu zu definieren. Oder Sie möchten Bruch deutlicher werden, wenn Abhängigkeiten gemischt.
Nachteile:
Anon Funktionen nicht nutzen kann, der Funktion hochziehen. Dies ist ein großer Unterschied. Ich neigen dazu, schwere Vorteil der Hub zu definieren, meine eigenen explizit benannt funcs-und Objekt-Konstruktoren in Richtung Boden und man die Objekt-definition und main-loop-Art Zeug an der Spitze. Ich finde es macht den code leichter zu Lesen, wenn Sie Namen für Ihre vars gut und erhalten einen breiten Blick auf, was Los ist, bevor Sie Strg-Fing für die details nur dann, wenn Sie Sie mögen. Hochziehen kann auch ein großer Vorteil im stark event-getrieben, Schnittstellen, wo die Einführung einer strengen Reihenfolge, was Wann kann dir in den Hintern beißt. Hochziehen hat eigene Vorbehalte (wie zirkuläre Referenz-potential), aber es ist ein sehr nützliches Werkzeug für die Organisation und macht code lesbar, wenn richtig eingesetzt.
Lesbarkeit/Debug. Absolut Sie gewöhnen sich viel zu stark in Zeiten, und es machen können debug-und code-Lesbarkeit ein Streit. Die codebase, die sich stark auf JQ, zum Beispiel, kann ein ernstes PITA zu Lesen und zu Debuggen, wenn Sie nicht einkapseln der Nähe-unvermeidlich anon-schwer und Massiv überlastet args $ Suppe in eine vernünftige Art und Weise. JQuery ' s hover-Methode, zum Beispiel, ist ein klassisches Beispiel für die über-die Verwendung der anon-funcs, wenn Sie fallen zwei anon funcs hinein, da es einfach für ein first-timer nehme an, es ist ein standard-Ereignis-listener-Zuordnung Methode eher als eine Methode überladen zu weisen-Handler für eine oder zwei Veranstaltungen.
$(this).hover(onMouseOver, onMouseOut)
ist viel mehr klar, als zwei anon funcs.InformationsquelleAutor der Antwort Erik Reppen
Mehr lesbar unter Verwendung der genannten Funktionen, und Sie sind auch in der Lage, auf sich selbst verweisende, wie im Beispiel unten.
http://jsfiddle.net/Yq2WD/
Dies ist schön, wenn Sie wollen, um eine sofort aufgerufen, Funktion, Referenzen selbst aber nicht hinzufügen zu den globalen namespace. Es ist immer noch lesbar, aber nicht verschmutzen. Ihren Kuchen haben und Essen es auf.
Hallo, mein name ist Jason ODER hi, mein name ist ???? Sie Holen.
InformationsquelleAutor der Antwort Jason Sebring
Etwas spät zur party, aber einige noch nicht erwähnte Aspekte zu Funktionen, anonyme oder anderweitig...
Anon funcs sind nicht einfach im Sinne Humanoide Gespräche über den code, der unter einem team. E. g., "Joe, könntest du erklären, was der Algorithmus tut, innerhalb dieser Funktion. ... Welches? Die 17 anonyme Funktion innerhalb der fooApp Funktion. ... Nein, nicht das! Der 17!"
Anon funcs anonym sind, um den debugger als gut. (duh!) Also die debugger-stack-trace wird in der Regel zeigen nur ein Fragezeichen oder ähnlich, so dass es weniger nützlich, wenn Sie mehrere Haltepunkte. Sie den Haltepunkt, sondern sich finden, scrollen Sie das debug-Fenster oben/unten, um herauszufinden, wo zur Hölle Sie sind in Ihrem Programm, weil, hey, Frage mark-Funktion funktioniert einfach nicht!
Bedenken über die Verschmutzung der globalen namespace gültig sind, aber leicht behoben werden, indem Sie die Benennung Ihrer Funktionen als Knoten innerhalb Ihrer eigenen root-Objekt, wie "myFooApp.happyFunc = Funktion ( ... ) { ... }; ".
Zur Verfügung stehenden Funktionen in den globalen Namensraum oder als Knoten in Ihrem root-Objekt wie oben angegeben, die aufgerufen werden können vom debugger direkt, während der Entwicklung und Debuggen. E. g., an der Konsole mit dem Befehl line, "myFooApp.happyFunc(42)". Dies ist eine extrem mächtige Fähigkeit, die nicht existiert (nativ) in kompilierten Programmiersprachen. Versuchen Sie das mal mit einem anon func.
Anon funcs gemacht werden können, besser lesbar, indem Sie Sie zu einer var und dann vorbei an der var als callback (statt inlining). E. g.:
var funky = function ( ... ) { ... };
jQuery('#otis').klicken Sie auf(funky);
Mit dem obigen Ansatz, könnten Sie möglicherweise Gruppe mehrere anon funcs an der Spitze des elterlichen func, dann unten, dass das Fleisch von sequentiellen Anweisungen wird viel enger gruppiert und einfacher zu Lesen.
InformationsquelleAutor der Antwort RickS