2010-12-27 6 views
4

Ich verstehe, wie Schließungen innerhalb von JavaScript funktionieren, aber meine Frage ist, warum würden Sie alle Schwierigkeiten einer Schließung durchlaufen, um eine Variable zu erhalten? Könnten Sie die Variable nicht einfach global machen? Oder würde das den globalen Spielraum überladen und Ihren Code anfällig für Fehler machen?Warum sind Closures besser als globale Variablen, um Variablen zu erhalten?

+7

"nicht versuchen zu prahlen", aber Sie tun es immer noch! – ThiefMaster

+4

@ThiefMaster: Er ist so gut darin zu prahlen es kommt einfach mühelos. –

+0

Nichts ist falsch mit prahlen, wenn Sie bereit sind, von Menschen, die darauf warten, Sie zu vermasseln, überprüft werden. – Josh

Antwort

1

Einer der Gründe ist, globale Verschmutzung zu verhindern. Die andere Möglichkeit besteht darin, dieselbe Implementierung für viele Operationen zu verwenden, indem einfach der übergebene Wert geändert wird.

js> makeadd = function(num) { return function(val) { return num+val } } 
function (num) { 
    return function (val) {return num + val;}; 
} 
js> add3 = makeadd(3) 
function (val) { 
    return num + val; 
} 
js> add4 = makeadd(4) 
function (val) { 
    return num + val; 
} 
js> add3(add4(2)) 
9 
6

Es ist ein Problem mit dem Scoping. Globale Variablen sind genau das: Global, alle. Mit Verschlüssen kann der Umfang (Sichtbarkeit) der Variablen besser kontrolliert werden, wodurch die möglichen unbeabsichtigten Nebenwirkungen besser kontrolliert werden können.

http://en.wikipedia.org/wiki/Global_variable

[Globals] sind in der Regel schlechte Praxis genau angesehen wegen ihrer Nicht-Lokalität: eine globale Variable kann potenziell von jedem Ort geändert werden (es sei denn, sie in den geschützten Speicher residieren), und ein Teil Das Programm kann davon abhängen. Eine globale Variable verfügt daher über ein unbegrenztes Potenzial zum Erstellen wechselseitiger Abhängigkeiten , und das Hinzufügen wechselseitiger Abhängigkeiten erhöht die Komplexität. Siehe action at a distance

2

Nun gibt nur eine globalen Namensraum in JavaScript ist, so wäre es ziemlich schwer sein, verschiedene Frameworks verwenden/Toolkits auf der gleichen Seite, denn früher oder später würden Variablennamen beginnen zu kollidieren.

Schließungen auch eine Möglichkeit bieten, um private Variablen zu emulieren:

function Counter(start) { 
    var count = start; 
    return { 
     increment: function() { 
      count++; 
     }, 

     get: function() { 
      return count; // only gives you the value, but no write access 
     } 
    } 
} 

Aber das ist ein eher „dumme“ Beispiel Verschlüsse sind besonders hilfreich, wenn es um Rückrufe aller Art kommt, wollen Sie nicht verwalten Globale Arrays, die die Daten für jeden Callback enthalten, sind sehr einfach und sauberer mit Closures.

Für eine extreme Verwendung von Verschlüssen werfen Sie einen Blick auf eine Klasse implementation für JavaScript. (Disclaimer, Code wurde von mir geschrieben.)

Hier proto Spur der rohen Eigenschaften jeder Klasse hält, aber es ist nach wie vor zur Verfügung extend die dann diese Eigenschaften auf andere Klassen hinzufügen kann, wenn sie von einem anderen erben.

1

Alle anderen bereits golbal Namen Verschmutzung und global is evil erwähnt haben, auch die OP:

oder wäre das Durcheinander auf den globalen Bereich ...

aber es gibt eine anderer Grund.

Es gibt nur eine Instanz einer globalen Variablen. Dies macht es nicht gut skalieren. Wenn Sie zu einem späteren Zeitpunkt mehr als eine Instanz des Objekts benötigen, müssen Sie entweder eine zweite globale Variable erstellen oder die ursprüngliche Variable in ein Array konvertieren und dieses Array manuell verwalten (dh selbst entscheiden, wann das Objekt gelöscht werden soll aus dem Gedächtnis).

Wenn es bereits durch eine Schließung erstellt wurde, kann das Erstellen der zweiten, dritten und vierten Instanz einfach durch Aufrufen der Funktion erfolgen, die die Schließung immer wieder neu erstellt. Sie erhalten außerdem den zusätzlichen Bonus, dass alle erstellten Instanzen automatisch Garbage Collected erhalten, wenn sie nicht mehr benötigt werden.

Diese Situation passiert öfter als Sie denken. Stellen Sie sich vor, Sie haben gerade eine Animationssequenz erstellt, indem Sie beispielsweise einen Text animieren, der eingeblendet wird. Und Sie haben eine globale Variable verwendet, um den Status der Animation zu verfolgen. Und du denkst, das ist großartig und alles ist gut und vergiss es. Einige Zeit später kommt dein Chef zu dir und sagt, er mag die Animation und möchte sie zu anderen Dingen auf der Seite hinzufügen. Nun müssen Sie sofort mit dem Umgang mit mehreren Animationen umgehen und diese global in ein Array umwandeln müssen eine Animation zu verhindern, dass eine andere laufende Animation clobbering .. wenn sie nur in Schließungen verkapselt wurden zu beginnen ...


Und was weißt du, gerade als ich nach dem Einreichen dieser Antwort herunterscrollte, fand ich eine Frage, die das Problem mit globalen Variablen illustriert: How do you create multiple timers on one page that operate independently -- javascript?. Für dieses spezielle Problem brauchen Sie keine Schließung, sondern nur alte lokale Variablen.

3

Zwei Wörter: Rennbedingungen.

Wenn Sie eine Variable im globalen Bereich während seiner beabsichtigten Verwendung zu einer Instanz Funktion lokal Sie das Risiko, dass zwei (oder mehr) eindeutige Instanzen Zugriff und Manipulation diese globale Variable ist und alle Instanzen verhalten laufen unvorhersehbar .

Es gibt viele andere Gründe, warum Sie sehr vorsichtig sein sollten, um den lokalen Zustand im globalen Raum zu speichern.

Man würde den Zustand der letzten Instanz, die diese Variable gesetzt hat, wiederverwenden (wenn nicht mehrere Instanzen gleichzeitig aktiv sind).

Es gibt auch mögliche Konflikte mit anderen Codeabschnitten, die auf einer globalen Variablen mit demselben Namen beruhen.

Ästhetisch machen Sie auch den globalen Namespace in ein Durcheinander (viele zufällige Variablen dort ohne irgendeine direkte Information, warum sie überhaupt dort sind).

Das Einfügen von Variablen in den globalen Raum ist fehleranfällig und macht die Laufzeitansicht durcheinander. Die Scoping-Möglichkeiten von JS machen es auch überflüssig, weshalb niemand es tut (außer für Dinge, die wirklich dorthin gehören).

Als zusätzlichen Kommentar, erwähnen Sie nicht Ihr Alter oder prahlen über Ihre Codierung Fähigkeiten in zukünftigen Fragen. Es ist nicht relevant für die Frage.

1

Beim Verlassen des Hauses ist es eine gute Idee, dem Nachbarn den Schlüssel zu geben, damit Ihr Ehepartner es für den Fall einsammeln kann, wenn er früh nach Hause kommt, aber es ist keine gute Idee, ihn auf die Straße zu werfen.