Verschlüsse Front to Back

Verschlüsse werden im Land von JavaScript oft als eine arkane Kunst angesehen. Einmal beherrscht, können Sie wirklich erstaunliches JavaScript schreiben. In diesem Artikel erfahren Sie mehr über die Magie von JavaScript-Verschlüssen.


Was ist eine Schließung??

Eine der Schlüsselwahrheiten von JavaScript ist das alles ist ein Objekt. Dies beinhaltet natürlich Funktionen.

Ein Abschluss ist nichts anderes als ein Funktionsobjekt mit einem zugehörigen Gültigkeitsbereich, in dem die Variablen der Funktion aufgelöst werden.

Verschlüsse erhalten ihren Namen aufgrund ihrer Art und Weise schließen über ihren Inhalt. Beachten Sie folgendes JavaScript:

 topping = "anchovi"; Funktion pizzaParty (numSlices) var topping = "pepperoni", innerFunction = function () var topping = "ham"; console.log ("... aber setze" + topping + "in" + numSlices + "Slices"); ; console.log ("Diese Pizza dreht sich alles um das" + Topping "); innerFunction ();  PizzaParty (3);

Wenn Sie Ihre Lieblingskonsole öffnen und den bösen Jungen ausführen, werden Sie mit einer köstlichen Nachricht begrüßt: "Diese Pizza dreht sich alles um die Peperoni ... Aber legen Sie Schinken auf 3 Scheiben." Dieses Beispiel veranschaulicht einige Schlüsselkonzepte von JavaScript, die für den Abschluss von Schließungen von entscheidender Bedeutung sind.

Ein Abschluss ist ein Funktionsobjekt

Wie viele Funktionsobjekte enthält der obige Code? Nun, wir haben unsere Pizza Party Funktion und verschachtelt in dieser Funktion ist innerFunction. Mathematik war nicht immer meine Stärke, aber 1 + 1 = 2 in meinem Buch. Jedes Funktionsobjekt verfügt über einen eigenen Satz von Variablen, die in jeder Funktion aufgelöst werden Umfang.

Eine Schließung hat ihren eigenen Umfang

Verschlüsse können nicht vollständig verstanden werden, ohne dass der Geltungsbereich fest verankert ist. Durch den Geltungsbereichsmechanismus von JavaScript kann jede Funktion ihre eigene haben Belag variabel, und ohne sie könnten wir zu viel Peperoni haben, zu wenig Schinken oder * keuchen * ... einige Sardellen auf unserer Pizza-Party. Lassen Sie uns eine kurze Illustration verwenden, um diese Idee besser zu veranschaulichen.

Funktionen werden mit dem Gültigkeitsbereich ausgeführt, der zum Zeitpunkt der Definition der Funktion gültig war. Es hat nichts mit dem Gültigkeitsbereich zu tun, wenn die Funktion aufgerufen wird.

Variable Eingabehilfe funktioniert außerhalb des Bereichs

Die grünen Pfeile zeigen an, dass die Zugänglichkeit von außen funktioniert. Innerhalb des Bereichs außerhalb einer Funktion definierte Variablen sind von innen her zugänglich.

Wenn wir das weglassen würden Belag variabel von innen Pizza Party Funktion, dann bekämen wir eine Nachricht wie "Diese Pizza dreht sich alles um den Anchovi", aber da Pizza Party hat ein Belag variabel in seinem eigenen Bereich; Diese salzigen Trottel kommen niemals in die Nähe unserer Pizza-Party.

Ebenso die numSlices Parameter ist von innen zugänglich innerFunction weil es im obigen Bereich definiert ist - in diesem Fall der Umfang von Pizza Party.

Variable Eingabehilfen funktionieren nicht von innen nach außen

Die roten Pfeile zeigen an, dass Variablen im Gültigkeitsbereich einer Funktion außerhalb dieser Funktion niemals zugänglich sind. Dies ist nur der Fall, wenn eine Variable eine der folgenden Bedingungen erfüllt:

  1. Das var Schlüsselwort wird verwendet.
  2. Die Variable ist ein Parameter für die Funktion oder eine äußere Funktion.
  3. Die Variable ist eine verschachtelte Funktion.

Das auslassen var Wenn ein Schlüsselwort beim Festlegen einer Variablen festgelegt wird, setzt JavaScript die nächstgelegene benannte Variable in äußeren Funktionen bis zum globalen Gültigkeitsbereich. An unserem Beispiel also dem Schinken Belag im innerFunction kann nicht von erreicht werden Pizza Party, und die Peperoni Belag im Pizza Party ist im globalen Geltungsbereich, in dem die Sardellen leben, nicht zugänglich.

JavaScript verwendet Lexical Scoping

Lexikalischer Bereich bedeutet, dass Funktionen unter Verwendung des gültigen Gültigkeitsbereichs ausgeführt werden, als die Funktion ausgeführt wurde definiert. Es hat nichts mit dem Gültigkeitsbereich zu tun, wenn die Funktion aufgerufen wird. Diese Tatsache ist entscheidend, um die Macht der Verschlüsse zu erschließen.

Nachdem wir nun verstanden haben, was eine Schließung ist und welche Bedeutung Schließungen haben, wollen wir uns mit einigen klassischen Anwendungsfällen beschäftigen.


Verwenden von Verschlüssen für den Datenschutz

Verschlüsse sind das So können Sie Ihren Code vor der Öffentlichkeit verbergen. Mit Verschlüssen können Sie leicht private Mitglieder haben, die von der Außenwelt abgeschirmt sind:

 (function (exportiert) function myPrivateMultiplyFunction (num, num2) return num * num2; // entspricht window.multiply = Funktion (num1, num2) … exports.multiply = Funktion (num1, num2) console.log (myPrivateMultiplyFunction (num1, num2));) (Fenster);

Mit Verschlüssen können Sie leicht private Mitglieder haben, die von der Außenwelt abgeschirmt sind.

Lass es uns brechen. Unser Funktionsobjekt auf oberster Ebene ist eine anonyme Funktion:

 (Funktion (Exporte) ) (Fenster);

Wir rufen diese anonyme Funktion sofort auf. Wir übergeben den globalen Kontext (Fenster in diesem Fall) können wir also eine öffentliche Funktion "exportieren", aber alles andere ausblenden. Weil die Funktion myPrivateMultiplyFunction ist eine verschachtelte Funktion, sie existiert nur im Rahmen unserer Schließung; Daher können wir es überall in diesem Bereich und nur in diesem Bereich verwenden.

JavaScript enthält einen Verweis auf unsere private Funktion zur Verwendung in der Multiplikationsfunktion myPrivateMultiplyFunction ist außerhalb der Schließung nicht zugänglich. Lass uns das ausprobieren:

 multiplizieren (2,6) // => 12 myPrivateMultiplyFunction (2,6) // => ReferenceError: myPrivateMultiplyFunction ist nicht definiert

Die Schließung hat es uns ermöglicht, eine Funktion für den privaten Gebrauch zu definieren, während wir weiterhin kontrollieren können, was der Rest der Welt sieht. Was können Verschlüsse sonst noch??


Verwenden von Verschlüssen für die Meta-Programmierung

Verschlüsse sind praktisch, wenn es um die Generierung von Code geht. Sind Sie es leid, sich all diese lästigen Tastencodes für Tastaturereignisse zu merken? Eine übliche Technik ist die Verwendung einer Schlüsselkarte:

 var KeyMap = "Enter": 13, "Shift": 16, "Tab": 9, "LeftArrow": 37;

In unserem Tastaturereignis möchten wir dann prüfen, ob eine bestimmte Taste gedrückt wurde:

 var txtInput = document.getElementById ('myTextInput'); txtInput.onkeypress = Funktion (e) var code = e.keyCode || e.was wie üblich für den Abruf der gedrückten Taste if (code === KeyMap.Enter) console.log (txtInput.value); 

Einen Moment in der Zeit festhalten

Das obige Beispiel ist nicht das schlechteste, aber wir können Meta-Programmierung und Closures verwenden, um eine noch bessere Lösung zu finden. Mit unserem bestehenden KeyMap Objekt können wir einige nützliche Funktionen erzeugen:

 for (var key in KeyMap) // greift auf ein Objekt mit Array-Zugriff zu, um den Funktionsnamen "dyanamic" zu setzen. KeyMap ["ist" + key] = (function (compare) return function (ev) var code = ev.keyCode | | ev.which; Rückkehrcode === compare;) (KeyMap [key]); 

Closures sind so leistungsfähig, weil sie die lokalen Variablen- und Parameterbindungen der Funktion erfassen können, in der sie definiert sind.

Diese Schleife erzeugt ein ist Funktion für jeden Key in KeyMap, und unser txtInput.onkeypress Funktion wird etwas lesbarer:

 var txtInput = document.getElementById ('myTextInput'); txtInput.onkeypress = Funktion (e) if (KeyMap.isEnter (e)) console.log (txtInput.value); 

Der Zauber beginnt hier:

 KeyMap ["ist" + Taste] = (Funktion (vergleiche) ) (KeyMap [Taste]); // sofort aufrufen und den aktuellen Wert an KeyMap [key] übergeben

Wie wir die Tasten einschleifen KeyMap, Wir übergeben den Wert, auf den dieser Schlüssel verweist, an die anonyme äußere Funktion und rufen ihn sofort auf. Dies bindet diesen Wert an vergleichen Sie Parameter dieser Funktion.

Die Schließung, an der wir interessiert sind, ist die, aus der anonymen Funktion wir zurückkehren:

 return Funktion (ev) var code = ev.keyCode || ev.which; Rückkehrcode === Vergleichen; 

Denken Sie daran, dass Funktionen mit dem Gültigkeitsbereich ausgeführt werden, der bei ihrer Definition vorhanden war. Das vergleichen Sie Parameter ist an den gebunden KeyMap Wert, der während einer Schleifeniteration vorhanden war, und daher kann unser verschachtelter Abschluss sie erfassen. Wir machen rechtzeitig eine Momentaufnahme des in diesem Moment wirkenden Umfangs.

Die Funktionen, die wir erstellt haben, erlauben es uns, die Einrichtung von zu überspringen Code Jedes Mal, wenn wir den Schlüsselcode ändern möchten, haben wir jetzt komfortable, lesbare Funktionen.


Verwenden von Closures, um die Sprache zu erweitern

An diesem Punkt sollte es relativ leicht zu erkennen sein, dass Verschlüsse für das Schreiben von erstklassigem JavaScript unerlässlich sind. Wenden wir das, was wir über Schließungen wissen, an, um einen der nativen Typen von JavaScript zu verbessern (keuchen!). Mit unserem Fokus auf Funktionsobjekte wollen wir das native erweitern Funktion Art:

 Function.prototype.cached = function () var self = this, // "this" bezieht sich auf die ursprüngliche Funktion cache = ; // unsere lokale, lexikalisch gespeicherte Cache-Speicher-Rückgabefunktion (args) if (args in cache) return cache [args]; return cache [args] = self (args); ; ;

Dieses kleine Juwel ermöglicht es jeder Funktion, eine zwischengespeicherte Version von sich selbst zu erstellen. Sie sehen, dass die Funktion selbst eine Funktion zurückgibt, so dass diese Erweiterung wie folgt angewendet und verwendet werden kann:

 Math.sin = Math.sin.cached (); Math.sin (1) // => 0.8414709848078965 Math.sin (1) // => 0.8414709848078965 wurde diesmal aus dem Cache gezogen

Beachten Sie die Schließkünste, die ins Spiel kommen. Wir haben einen Einheimischen Zwischenspeicher Variable, die privat bleibt und von der Außenwelt abgeschirmt ist. Dadurch werden Manipulationen verhindert, die unseren Cache ungültig machen könnten.

Der zurückgegebene Abschluss hat Zugriff auf die äußeren Bindungen der äußeren Funktion. Dies bedeutet, dass wir eine Funktion mit vollem Zugriff auf den Cache im Inneren sowie die ursprüngliche Funktion zurückgeben können! Diese kleine Funktion kann Wunder für die Leistung bewirken. Diese spezielle Erweiterung ist so eingerichtet, dass sie nur ein Argument behandelt. Ich würde mich jedoch sehr freuen, wenn Sie eine Cache-Funktion mit mehreren Argumenten verwenden.


Schließungen in freier Wildbahn

Lassen Sie uns als zusätzlichen Bonus einige Verwendungsmöglichkeiten von Verschlüssen in freier Wildbahn betrachten.

jQuery

Manchmal die berühmte jQuery $ Factory ist nicht verfügbar (denken Sie an WordPress), und wir möchten es wie üblich verwenden. Anstatt nach zu greifen jQuery.noConflict, Wir können einen Verschluss verwenden, um Funktionen innerhalb unseres Systems Zugriff zu gewähren $ Parameterbindung.

 (function ($) $ (document) .ready (function () // business as usual…);) (jQuery);

Backbone.js

Bei großen Backbone.js-Projekten kann es vorteilhaft sein, Ihre Anwendungsmodelle privat zu haben und dann eine öffentliche API in der Hauptanwendungsansicht bereitzustellen. Mit einer Schließung können Sie diese Privatsphäre leicht erreichen.

 (Funktion (Export)) var Product = Backbone.Model.extend (urlRoot: '/ products',); var ProductList = Backbone.Collection.extend (url: '/ products', Modell: Product); var Produkte = neue Produktliste; var ShoppingCartView = Backbone.View.extend (addProduct: function (Produkt, Optionen) return CartItems.create (Produkt, Optionen);, removeProduct: Funktion (Produkt, Optionen) Products.remove (Produkt , opts);, getProduct: function (productId) return Products.get (productId);, getProducts: function () return Products.models;); // Export der Hauptanwendungsansicht nur exports.ShoppingCart = neue ShoppingCartView;) (Fenster);

Fazit

Eine kurze Zusammenfassung des Gelernten:

  • Ein Abschluss ist nichts anderes als ein Funktionsobjekt mit einem Gültigkeitsbereich.
  • Schließungen erhalten ihren Namen durch die Art und Weise, wie sie ihren Inhalt "schließen".
  • Verschlüsse machen sich im JavaScript-Bereich von JavaScript bezahlt.
  • Verschlüsse sind der Weg, um Datenschutz in JavaScript zu erreichen.
  • Closures können die lokalen Variablen- und Parameterbindungen einer äußeren Funktion erfassen.
  • JavaScript kann mit etwas Schließmagie stark erweitert werden.
  • Verschlüsse können mit vielen Ihrer Lieblingsbibliotheken verwendet werden, um sie noch kühler zu machen!

Vielen Dank fürs Lesen! Fühlen Sie sich frei, um Fragen zu stellen. Nun lasst uns die Pizza-Party genießen!