Heim  >  Artikel  >  Backend-Entwicklung  >  Wie man Abschlüsse und Klassen in js versteht

Wie man Abschlüsse und Klassen in js versteht

一个新手
一个新手Original
2017-10-23 09:22:291652Durchsuche

Abschluss

Schauen wir uns zunächst die Definition aus Wikipedia an

In der Informatik wird Abschluss (englisch: Closure) auch als lexikalischer Abschluss (Lexical Closure) oder Funktionsverschluss bezeichnet sind Funktionen, die auf freie Variablen verweisen. Die referenzierte freie Variable verbleibt bei der Funktion, auch nachdem sie die Umgebung, in der sie erstellt wurde, verlassen hat. Daher kann man auch anders sagen, dass ein Abschluss eine Entität ist, die aus einer Funktion und der zugehörigen Referenzumgebung besteht. Abschlüsse können zur Laufzeit mehrere Instanzen haben, und unterschiedliche Referenzumgebungen und dieselbe Funktionskombination können unterschiedliche Instanzen erzeugen.

Um diesen Satz einfach zu verstehen, gibt es zwei wichtige Punkte:
1. Freie Variable 2. Funktion (Referenzierung auf freie Variable).

Lassen Sie uns zunächst über freie Variablen sprechen:

Wenn wir eine Variable definieren und keine Einschränkungen für sie festlegen, handelt es sich um eine freie Variable. Zum Beispiel:

x ∈  (0,99)
f(x,y)

In der Funktion f(x,y) ist x die Einschränkungsvariable und y die freie Variable.

Speziell in JavaScript schauen wir uns ein Beispiel an:


var x = 0;
function foo (y) {
    var z = 2;
    return x + y + z;}foo (3); // 3

Umgerechnet in mathematisches Denken sollte die Funktion foo eigentlich so aussehen: foo (x, y), aber wir wissen, dass die Parameter der Funktion tatsächlich durch die Funktion eingeschränkt werden, das heißt, die tatsächliche freie Variable ist nur x.
Dies kann zu einer einfachen Definition führen: Wenn es in einer Funktion eine Variable gibt, die weder eine lokale Variable noch ein formaler Parameter ist, können wir uns vorstellen, dass sie einen Abschluss bildet.

Woher kommen freie Variablen?

In fast allen Sprachen werden Variablen mit demselben Namen zunächst in diesem Bereich durchsucht. Wenn sie sie nicht finden, werden sie in den übergeordneten Bereich durchsucht. Wir nennen dies eine Bereichskette.
In einer Abschlussfunktion werden freie Variablen normalerweise vom übergeordneten Element bereitgestellt. Schauen Sie sich das folgende Beispiel an:


function foo(x) {
    var tmp = 3;
    function bar(y) {
        console.log(x + y + (++tmp));
    }
    bar(10);}foo(2)

Gemäß unserer obigen Definition hat bar freie Variablen und ist ein Abschluss, foo jedoch nicht.
Wie können wir also foo zu einem Abschluss machen?


var x = 0;function foo() {
    var tmp = 3;
    function bar(y) {
        console.log(x + y + (++tmp));
    }
    bar(10);}// 其实转换一下,形如function foo2() {
    var tmp = 3;
    //function bar(y) {
        console.log(x + 10 + (++tmp));
    //}
    // bar(10);}

An diesem Punkt kann foo als Schließung betrachtet werden.
An diesem Punkt denken einige Freunde vielleicht, dass dies sich von den js-Verschlüssen unterscheidet, die wir normalerweise sehen. Die Verschlüsse, die wir normalerweise sehen, sind wie folgt: Das Beispiel stammt aus diesem Blog


function foo(x) {
    var tmp = new Number(3);
    return function (y) {
        alert(x + y + (++tmp));
    }}var bar = foo(2); // bar 现在是一个闭包bar(10);

Diese Funktion kann tatsächlich wie folgt umgeschrieben werden:


bar = function (y) {
    // foo(2)
    alert(2 + y + (++tmp))}

Offensichtlich ist tmp eine freie Variable, die unserer ursprünglichen Definition entspricht, nämlich bar eine Funktion mit freien Variablen.
Wo existiert also tmp?
Wenn foo(2) ausgeführt wird, wird eine Variable mit tmp=3 generiert. Auf diese Variable wird von der Rückgabefunktion verwiesen, sodass sie nicht recycelt wird. Die freien Variablen in der Rückgabefunktion finden Werte gemäß der Bereichskette. Die Bar-Funktion ist in foo(2) definiert, daher wird zunächst im Variablenbereich von foo(2) nach der Variablen tmp gesucht und diese bearbeitet.

Hinweis: Was das Thema Scope Chain angeht, werde ich es im nächsten Artikel analysieren.

Apropos, fügen Sie den Modulmodus ein.

Modulmodus für die Verwendung von Abschlüssen


var Module = (function () {
    var aaa = 0;
    var foo = function () {
        console.log(aaa);
    }
    
    return {
        Foo: foo    }})();// 或者(function () {
    var aaa = 0;
    var foo = function () {
        console.log(aaa);
    }
    
    window.Module = {
        Foo: foo    }})();

Beachten Sie die beiden obigen Beispiele: Das Modul selbst ist nur ein Objekt, aber die Rückgabefunktion selbst bildet Abschlüsse Stellen Sie sicher, dass das Oszilloskop sauber ist und keine anderen Funktionen beeinträchtigt.

Apropos, einige Freunde denken bestimmt, dass dies eine alternative Kategorie ist? Verfügen Sie über lokale Variablen und zugängliche Funktionen. Ja, vom Aussehen her denke ich, dass Abschlüsse und Klassen sehr ähnlich sind.

Klasse

Nehmen Sie Java als Beispiel:


class Foo {    
    private int a;    
    int Say( int b ) {        
    return a + b; 
    }  
}

Im obigen Foo liegt das a in der Funktion Say außerhalb von Funktionsumfang ist eine freie Variable. Say kann als Funktionsabschluss betrachtet werden. Der Unterschied zu js besteht jedoch darin, dass Instanzmethoden über Instanzen von Klassen, also Objekten, aufgerufen werden müssen.
Im Java-Design sind die Zugriffsrechte „Privat“, „Schutz“, „Standard“ und „Paket“ klar definiert, was eine Pionierarbeit bei der Standardisierung von Aufrufen darstellt. Dies führt auch dazu, dass Java-Programmierer die Implementierung von Abschlüssen selten in Betracht ziehen, da Variablen und Funktionen Schlüsselwörter zum Definieren von Zugriffsberechtigungen haben und zu jeder Klasse gehören, was klar und deutlich ist.

Nachteile von Abschlüssen

Wenn Sie Abschlüsse im Hinblick auf die Klassenimplementierung verstehen, ist es leicht zu verstehen, warum die Verwendung von Abschlüssen nicht empfohlen wird.
Jedes Mal, wenn ein Abschluss aufgerufen wird, wird ein Bereich generiert, um einige freie Variablen zu speichern, die für die Abschlussfunktion erforderlich sind. Dies kann leicht zu Speicherverschwendung führen. Selbst bei der Java-Programmierung wird nicht empfohlen, beiläufig neue Objekte zu erstellen.

Exkurs

Im vorherigen Artikel „Binden, Aufrufen, Anwenden“ habe ich einen Punkt erwähnt: Da es objektorientiert ist, besteht die Notwendigkeit, dies zu binden.
In Bezug auf die Objektorientierung denke ich, dass der Vorteil der Objektorientierung darin besteht, dass sie leicht zu verstehen, zu warten und wiederzuverwenden ist. Dies übertrifft die Leistungsanforderungen bei der Entwicklung großer Projekte durch mehrere Personen bei weitem.
Selbst jetzt, wo das Mooresche Gesetz langsamer wird, ist Speicher im Vergleich zu früher sehr billig, sodass die Leistungsanforderungen seit der Antike extrem waren und jetzt die Lesbarkeit des Codes allgemein befürwortet wird.
Es gibt Superexperten, die diese bunte Welt des Codes geschaffen haben, um mehr Menschen den Spaß am Programmieren erleben zu lassen, sie haben einfacher verständliche Programmiersprachen entworfen und verschiedene Compiler und Parser erfunden...
Wenn Sie nur ein 1+1-Programm schreiben, besteht keine Notwendigkeit, objektorientiert zu sein. Wenn Menschen über eine superstarke Logik und ein starkes Gedächtnis mit Maschinen verfügen können, besteht keine Notwendigkeit, objektorientiert zu sein.

Das obige ist der detaillierte Inhalt vonWie man Abschlüsse und Klassen in js versteht. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn