Warum ist es in JavaScript so weit verbreitet, große anonyme Funktionen als Argumente an andere Funktionen zu übergeben?

27

Ich bin der Meinung, dass die Weitergabe anonymer Funktionen, die mehr als ein paar Codezeilen enthalten, als Argumente für andere Funktionen die Lesbarkeit und Selbstdokumentation drastisch bis zu dem Punkt beeinträchtigt, an dem ich dies für wahrscheinlich halte Weitaus besser für alle, die wahrscheinlich den Code verwenden, um nur eine benannte Funktion zu deklarieren. Oder zumindest assign , dass anonyme Funktion einer Variablen , bevor Sie die Erklärung der Hauptfunktion

Viele JavaScript- Bibliotheken (jQuery, d3.js / NVD3.js) verwenden auf diese Weise jedoch große Funktionen, um nur einige Beispiele zu nennen.

Warum ist dies in JavaScript so weit verbreitet? Handelt es sich um eine kulturelle Sache, oder fehlen mir Vorteile, die die Verwendung bevorzugter machen würden als eine benannte Funktion zu deklarieren?

Adam Copley
quelle
1
Es hat wahrscheinlich viel mit der Verwendung von Verschlüssen zu tun . Dies kann auch damit zusammenhängen, dass die eigentliche Funktion nicht der Außenwelt zugänglich gemacht werden soll (weshalb sie anonym ist).
Robert Harvey
3
@RobertHarvey Mit anderen Worten, es ist eine Problemumgehung für JavaScript, das nicht öffentlich und privat ist .
Mason Wheeler
2
An vielen Stellen liest sich eine große anonyme Funktion eher wie ein Block und fühlt sich im Allgemeinen ziemlich gut an, wenn Sie sich daran gewöhnt haben. Scoping-Regeln unterstützen sogar das Blockgefühl.
5
@MasonWheeler: Das hängt von deiner Perspektive ab. Ein Schema- oder ECMAScript-Programmierer könnte dies publicals privateProblemumgehung für nicht ordnungsgemäße Abschlüsse bezeichnen.
Jörg W Mittag
1
@ JörgWMittag Hurra für Racket, den offiziellen Sprachsponsor von XKCD 927!
Mason Wheeler

Antworten:

23

Drei Hauptgründe, die mir einfallen:

  1. Zugriff auf den übergeordneten Bereich
  2. Privatsphäre
  3. Reduzierung der in höheren Bereichen definierten Namen

Zugriff auf übergeordnete Bereiche : Inline-Funktionsdefinitionen ermöglichen dem Inline-Code den Zugriff auf Variablen, die in übergeordneten Bereichen definiert sind. Dies kann für viele Dinge sehr nützlich sein und bei richtiger Ausführung die Menge oder Komplexität des Codes verringern.

Wenn Sie den Code in eine außerhalb dieses Bereichs definierte Funktion einfügen und dann den Code aufrufen, müssen Sie einen beliebigen übergeordneten Status übergeben, auf den der Code zugreifen soll.

Datenschutz: Code in einer anonymen Inline-Definition ist privater und kann von keinem anderen Code aufgerufen werden.

Reduzierung der in höheren Bereichen definierten Namen: Dies ist besonders wichtig, wenn Sie im globalen Bereich arbeiten. Bei einer anonymen Inline-Deklaration muss jedoch im aktuellen Bereich kein neues Symbol definiert werden. Da Javascript von Haus aus keine Namespaces erfordert, ist es ratsam, nicht mehr globale Symbole zu definieren, als nur minimal erforderlich sind.


Editorial: Es scheint zu einer kulturellen Angelegenheit in Javascript geworden zu sein, bei der anonymes Inline-Deklarieren irgendwie als "besser" angesehen wird, als eine Funktion zu definieren und aufzurufen, selbst wenn der Zugriff auf den übergeordneten Bereich nicht verwendet wird. Ich vermute, dies lag anfangs an dem Problem der globalen Namespace-Verschmutzung in Javascript, dann vielleicht an Datenschutzproblemen. Aber es hat sich mittlerweile zu einer kulturellen Sache entwickelt und man kann es in vielen öffentlichen Code-Körpern (wie den von Ihnen erwähnten) sehen.

In Sprachen wie C ++ halten es die meisten wahrscheinlich für eine weniger als ideale Praxis, eine Riesenfunktion zu haben, die sich über viele Seiten / Bildschirme erstreckt. Natürlich ist in C ++ ein Namespace integriert, es bietet keinen Zugriff auf den übergeordneten Bereich und verfügt über Datenschutzfunktionen, so dass die Lesbarkeit / Wartbarkeit die Hauptgründe für die Verwendung des Codeausdrucks darstellt, um auf den Datenschutz und den Zugriff auf den übergeordneten Bereich zuzugreifen. JS scheint einfach in eine andere Richtung motiviert worden zu sein, und es ist zu einer kulturellen Sache innerhalb der Sprache geworden, selbst wenn die Dinge, die diese Richtung motiviert haben, in einem bestimmten Fall nicht benötigt werden.

jfriend00
quelle
Da ein C ++ - Entwickler kürzlich für einen Großteil meiner Arbeit zu JS gewechselt ist, ist diese Antwort sehr sinnvoll, insbesondere für den übergeordneten Zugriffspunkt - er kann Ihren Code wirklich erheblich vereinfachen. Ein Nitpick - C ++ bietet Zugriff auf übergeordnete Bereiche in C ++ 11-Lambdas :) Auf jeden Fall +1.
Kommandant Koriander Salamander
8

Anonyme Funktionen werden in JavaScript für viel mehr Zwecke verwendet als in den meisten anderen Sprachen.

Erstens werden sie für den Namespace und das Block-Scoping verwendet. Bis vor kurzem fehlten in JavaScript Module oder andere Namespace-Mechanismen, die dazu geführt haben, dass anonyme Funktionen verwendet wurden, um diese Funktionalität über das Modulmuster bereitzustellen. Die Benennung dieser Funktionen würde absolut keinen Nutzen bringen. In kleinerem Maßstab, aufgrund JavaScript Mangel an Block Scoping bis vor kurzem wurde ein ähnliches Muster zu imitieren Block Scoping verwendet; vor allem im Körper von Schleifen. Die Verwendung einer benannten Funktion wäre in diesem Fall aktiv verschleiert.

Zweitens und weniger JavaScript-spezifisch werden anonyme Funktionen häufig mit Funktionen höherer Ordnung verwendet, die Kontrollstrukturen imitieren. Zum Beispiel die eachMethode von jQuery . Ich bezweifle, dass Sie jeden Schleifenkörper oder jeden If-Zweig in eine Funktion abstrahieren, wenn er länger als ein paar Zeilen ist. In diesem Fall gilt die gleiche Logik.

Ein letzter Grund ist, dass ereignisbasierte Programmierung in JavaScript häufig vorkommt, was dazu führt, dass versehentlich ein Stilcode für die Weitergabe verwendet wird. Sie tätigen einen AJAX-Aufruf und registrieren einen Rückruf, der bei Ausführung einen weiteren AJAX-Aufruf ausführt und einen Rückruf usw. registriert. Wenn die Aufrufe nicht asynchron, sondern synchron wären, wäre dies nur eine gerade Codesequenz in einem einzigen lexikalischen Bereich . Auch hier bezweifle ich, dass Sie alle paar Zeilen linearen Codes in eine Funktion abstrahieren würden.

Es gibt auch kulturelle Faktoren, und aus den oben genannten Gründen sind anonyme Funktionen in JavaScript weitaus häufiger als in vielen anderen Sprachen und werden bequemer / nachlässiger als in vielen anderen Sprachen verwendet.

Derek Elkins
quelle
Meine eigenen, vielleicht naiven Strukturen in C ++ haben manchmal Prinzipien der ereignisbasierten Codierung und Rückrufe von JavaScript über std :: function und lambdas übernommen. In meinem Fall liegt dies teilweise daran, dass ich UI-Code in C ++ ausführe und keine Blockierungsoperationen ausführen möchte. Ich bin neugierig, ob die Praktiken von JavaScript für irgendjemanden einfach nützlich sind, solange die Sprache sie gut unterstützt.
Katana314