Warum ist das Schließen für JavaScript wichtig?

16

Der Lambda-Ausdruck von C # hat ebenfalls Abschlüsse , wird jedoch in den C # -Gemeinschaften oder Büchern selten diskutiert. Ich sehe weit mehr JavaScript-Leute und -Bücher über seine Schließungen als in der C # -Welt. Warum das?

TomCaps
quelle
3
Weil JavaScript als erstklassige funktionale Sprache behandelt wird und C # eine klassische OOP-Sprache ist. Unterschiedliche Paradigmen, unterschiedliche Programmierstile.
Raynos
1
Erstklassige Funktionen machen die Sprache zu einer funktionalen Sprache. PHP (seit 5.3), Python oder D haben erstklassige Funktionen. Würden Sie sagen, dass es sich um funktionale Sprachen handelt? Mit Sicherheit nicht, und Javascript auch nicht.
Deadalnix
1
@deadalnix JavaScript ist eine Multi-Paradigmen-Sprache. Es unterstützt hauptsächlich das prozedurale, funktionale und prototypische OO-Paradigma. Es ist keineswegs eine reine funktionale Sprache, aber Sie können leicht Javascript in das funktionale Paradigma schreiben, ohne die Sprache zu verbiegen. Ich würde das gleiche von C # und Python sagen.
Raynos
3
@deadalnix, eine Sprache, mit der Sie einen Y-Kombinator definieren können, ist eine funktionale Sprache. Per Definition.
SK-logic
1
@deadalnix: Ich nehme an, was es ankommt, ist die Frage , welche Ansätze gefördert durch die Sprache. Es gibt viele JavaScript-Frameworks und -Plattformen (insbesondere node.js und DOM (Ereignismodell)), die sich stark auf Funktionen erster Ordnung stützen. PHP hat die Funktionen, die den gleichen Programmierstil ermöglichen, aber wenn Sie sich die Standard-API oder viele Frameworks ansehen, sehen Sie, dass dies nicht wirklich der Kern der Sprache ist.
back2dos

Antworten:

5

Weil Javascript keine Funktionen wie Namespaces hat und Sie ziemlich leicht mit allen Arten von globalen Objekten durcheinander kommen können.

Daher ist es wichtig, Code in seiner eigenen Ausführungsumgebung zu isolieren. Dann bist du in Closure genau richtig.

Diese Verwendung von Closure ist in einer Sprache wie C # nicht sinnvoll, in der Namespaces, Klassen usw. vorhanden sind, um Code zu isolieren und nicht alle Elemente in den globalen Bereich einzubeziehen.

Eine sehr verbreitete Praxis für Javascript-Code ist es, wie folgt zu schreiben:

(function(){
    // Some code
})();

Wie Sie sehen, handelt es sich um eine anonyme Funktionsdeklaration, auf die die Ausführung sofort folgt. Somit ist es nicht möglich, von außen auf alle in der Funktion definierten Elemente zuzugreifen, und Sie werden den globalen Bereich nicht durcheinander bringen. Der Ausführungskontext dieser Funktion bleibt so lange erhalten, wie Code sie verwendet, wie in diesem Kontext definierte verschachtelte Funktionen, die Sie als Rückruf oder was auch immer übergeben können.

Javascript ist eine ganz andere Sprache als C #. Es ist nicht objektorientiert, es ist prototyporientiert. Dies führt am Ende zu sehr unterschiedlichen Praktiken.

Wie auch immer, Verschlüsse sind gut, also benutze sie auch in C #!

EDIT: Nach einigen Diskussionen über den Chat von stackoverflow denke ich, dass diese Antwort präzise sein muss.

Die Funktion im Beispielcode ist kein Abschluss. Diese Funktion kann jedoch lokale Variablen und verschachtelte Funktionen definieren. Alle verschachtelten Funktionen, die diese lokalen Variablen verwenden, sind Abschlüsse.

Dies ist nützlich, um einige Daten über eine Reihe von Funktionen hinweg gemeinsam zu nutzen, ohne den globalen Umfang zu beeinträchtigen. Dies ist die häufigste Verwendung von Schließung in Javascript.

Closure ist weitaus leistungsfähiger als das bloße Teilen einiger Daten, aber seien wir realistisch, die meisten Programmierer wissen nichts über funktionale Programmierung. In C # hätten Sie für diese Art der Verwendung eine Klasse oder einen Namespace verwendet, aber JS bietet diese Funktionalität nicht.

Mit Closure können Sie weit mehr tun, als nur den globalen Geltungsbereich zu schützen. Dies wird jedoch im JS-Quellcode deutlich.

deadalnix
quelle
9
Das ist keine Schließung. Sie beschreiben den Vorteil der Verwendung von Funktionen zum Erstellen eines lokalen Bereichs.
Raynos
2
Ein Closure ist nur dann ein Closure, wenn es über freie Variablen hinausgeht. Vielen Dank auch, dass Sie mir
gesagt haben
2
Statt mich zu untergraben, indem Sie mich als Anfänger bezeichnen, können Sie im Chat-Raum von JavaScript SO auch konkrete Argumente vorbringen . Diese Diskussion gehört nicht wirklich hierher, aber ich werde Ihre Missverständnisse gerne im SO-Chat diskutieren.
Raynos
1
Abgestimmt. JavaScript ist sehr objektorientiert. Es ist einfach nicht klassenbasiert, aber eine solche Funktionalität ist leicht zu erstellen. Es hat erstklassige Funktionen, nutzt Verschlüsse, um es zu einem natürlichen System für stark ereignisgesteuerte Paradigmen zu machen, und laut Autor Brendan Eich war Scheme die Hauptinspirationsquelle. Ich bin mir nicht sicher, was Sie für eine funktionale Sprache halten, aber das Komische ist, dass Sie anscheinend der Meinung sind, dass klassenbasierte Vererbung eher kritisch als nicht mehr unbedingt erforderlich ist, wenn Sie Funktionen weitergeben und in neuen Kontexten anwenden können.
Erik Reppen
2
-1 auch. Dies beschreibt keine Verschlüsse, sondern den Umfang.
Izkata
12

Wahrscheinlich, weil gängige Implementierungen der Objektorientierung von JavaScript von Closures abhängen. Schauen wir uns ein einfaches Beispiel an:

function counter() {
   var value = 0;
   this.getValue = function() { return value; }
   this.increase = function() { value++; }
}

var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());

Die Methoden getValueund increasesind tatsächlich Abschlüsse, die die Variable einkapseln value.

user281377
quelle
3
-1 "hängt von Verschlüssen ab" Das ist sehr subjektiv. Es tut nicht.
Raynos
Raynos: Möchten Sie uns zeigen, wie Sie private Mitglieder ohne Sperren erstellen und verwenden können?
user281377
1
@ammoQ so etwas wie privat gibt es in JavaScript nicht. Was Sie meinten, war "weil die klassische JavaScript-OO-Emulation von Schließungen abhängt". JavaScript OO ist ein Prototyp, der ein anderes Paradigma darstellt. Es ist jedoch eine gute Antwort auf die Frage: "Wir verwenden Closures in JavaScript, weil dort die klassische OO emuliert werden musste"
Raynos,
1
@keppla Ich meinte "OO hängt von Verschlüssen ab" ist subjektiv. Sie brauchen überhaupt keine Verschlüsse für OO.
Raynos
2
du machst mich zur rep-
hure, die
4

Weil viele der Bibliotheken, die JavaScript "erträglich" machen, sie verwenden.

Schauen Sie sich JQuery , Prototype oder MooTools an , um nur drei beliebte zu nennen. Jede dieser Bibliotheken stellt eine eachMethode für ihre Sammlungen als bevorzugte Methode für die Iteration bereit , die eine Iteratorfunktion verwendet. Diese Funktion ist beim Zugriff auf Werte im äußeren Bereich ein Abschluss:

[1,2,3].each(function(item) {
   console.log(item);
});

Und hier hört es nicht auf: Callbacks in Ajax, Event-Handling in Ext.js usw. übernehmen alle Funktionen, und wenn Sie Ihren Code nicht mit 100 Millionen Funktionen aufblähen möchten, die genau einmal aufgerufen werden, sind Closures der richtige Weg.

keppla
quelle
1
Warum ist es keine Schließung? console.logWird in einem äußeren Bereich definiert, so consoleist eine "freie Variable". Und warum ist eigentlich eine for-Schleife, die nichts anderes macht, eine schlechte Übung?
Keppla
@Raynos: Meine Definition von Closure ist 'Block, der eine freie Variable enthält', dieser Status geht nicht verloren, die freie Variable befindet sich zufällig im oberen Bereich. Aber um meinen Standpunkt zu unterstützen, betrachten Sie diese Methode: pastie.org/2144689 . Warum sollte das schlecht sein?
Keppla
Ich denke immer noch, dass das "Schließen" globaler Daten als Betrug betrachtet wird. Ich bin damit einverstanden, dass der Zugriff auf Daten in der Scope-Kette in Ordnung ist. Es ist einfach eine gute Praxis, diesen Zugriff zu minimieren.
Raynos
Einigung
Es sollte beachtet werden, dass es bei Array-Iteratoren (für jedes, jede Karte, jede Reduzierung usw.) keinen Grund dafür gibt, dass sie Closures sind. Sie haben alle Zustände, die direkt an sie übergeben werden. Ich würde es als Anti-Muster für sie betrachten, Schließungen zu sein
Raynos
3

Ich stimme den anderen Antworten zu, dass eine "gute" Codierung mit JavaScript stärker von Schließungen abhängig ist. Darüber hinaus ist es jedoch wahrscheinlich nur eine Frage, wie lange die Funktion in jeder Sprache bereits verfügbar ist. JavaScript hat im Grunde genommen seit den frühesten Implementierungen Schließungen. C # dagegen hat sie erst seit 3.0, das mit Visual Studio 2008 veröffentlicht wurde.

Viele C # -Programmierer, auf die ich stoße, arbeiten noch an 2.0-Projekten. Und selbst wenn sie in 3.0 oder 4.0 arbeiten, verwenden sie häufig immer noch 2.0-Redewendungen. Ich liebe Verschlüsse; Hoffentlich werden sie in C # häufiger verwendet, da sich das Konzept unter C # -Entwicklern verbreitet.

RationalGeek
quelle
2

Der Hauptgrund dafür ist, dass C # statisch typisiert ist und Funktionen nur auf eine einzige, vorgegebene Umgebung zugreifen können, was die Nützlichkeit von Closures beeinträchtigt.

In JavaScript hingegen ermöglichen Closures, dass sich Funktionen beim Zugriff als Objekteigenschaft wie Methoden verhalten. Da es sich um erstklassige Objekte handelt, können sie auch in verschiedene Umgebungen eingefügt werden, sodass Subroutinen in verschiedenen Kontexten ausgeführt werden können.

Filip Dupanović
quelle
1
Was hat statische Typisierung damit zu tun? Verschlüsse sind orthogonal.