[JavaScript] Java-Programmierer! Sie können das Schließen von JavaScript sehr leicht verstehen!

Über diesen Artikel

Zweck dieses Artikels

Ich möchte die Technologie des JavaScript-Schließens aus einer anderen Perspektive erläutern. Da Java für die Erklärung verwendet wird, sind Grundkenntnisse in Java (dh Klassendefinition und neu) erforderlich.

Zielperson

――Ich habe verschiedene Erklärungen zur Schließung gelesen und angehört, aber es ist nicht ganz richtig. Oder ich verstehe überhaupt nicht. Aber mit Java wissen Sie ein wenig? Wie ist das?

Was ist eine Schließung?

Dann ist es aus der Schlussfolgerung sofort. Was ist eine Schließung?

Sagst du Ist das in Ordnung? Was ist eine Schließung?

** Eine Klasse mit nur einer Methode (wie ein Mon) **

Ach du lieber Gott. Ich habe es dir gesagt. Ich werde mehr erklären als ich sagte.

Beispiel: Zähler

Es ist schnell, aber ich möchte mit einem Beispiel beginnen. In der Beschreibung des Verschlusses gibt es oft ein Beispiel "Machen wir einen Zähler!". Ich denke nicht, dass dies als Beispiel falsch ist, deshalb werde ich auch hier die Verwendung des Zählers als Beispiel erklären. Unten sehen Sie ein Beispiel für einen in Closure!

            //Machen Sie einen Verschluss
function createCounter() {  //Schließung, um einen Zähler zu machen
    var count=0;            //Eine Variable, die den Wert des Zählers speichert

    return function() {     //Funktionsdeklaration in Funktion
        return ++count;     //Erhöhen Sie den Wert des Zählers und kehren Sie dann zurück
    };
};

Aha. Ich weiß es nicht. JavaScript hat eine ähnliche Grammatik wie Java, ist aber anders. .. ..

Mal sehen, wie man es benutzt, ohne es zu wissen.

            //Verwenden Sie einen Verschluss
var cntA=createCounter();            //Zähler A erstellen
console.log(cntA());                    //1 wird zuerst angezeigt
console.log(cntA());                    //Dann wird 2 angezeigt
console.log(cntA());                    //Dann wird 3 angezeigt

var cntB=createCounter();            //Zähler erstellen B.
console.log(cntB());                    //1 wird zuerst angezeigt
console.log(cntB());                    //Dann wird 2 angezeigt
console.log(cntB());                    //Dann wird 3 angezeigt

[Ergebnis]

1
2
3
1
2
3

Hmm. .. .. ...... Ich weiß nicht, was es bedeutet, eine Schließung zu sein. Ich denke, dass.

Lassen Sie uns einen zweiten Blick darauf werfen und dies in Java neu schreiben. Dann ist es ganz einfach. Ich denke, "Was? Ist das alles?", So ernst.

Java-Beispiel

Lassen Sie uns nun genau dasselbe (dh die Gegenklasse) in Java erstellen. Lass uns gehen? Dies ist ein Beispiel für Java!

class Counter            //Gegenklasse
{
  private int count;      //Feld mit dem Wert des Zählers
  public int add()        //Methode zum Hinzufügen
  {
    count ++;             //Ich addiere den Zählerwert
    return count;         //Und zurück
  }
}

Aus der Sicht derer, die Java verwenden können, ist es ein Zähler, egal wie Sie es betrachten. Die Grundlagen der Klassenerstellung. Es gibt keine schwierigen Punkte. Es ist leicht zu Tode zu verstehen. Weiter ist, wie man es benutzt. Erstellen Sie zwei Instanzen (cntA, cntB) und rufen Sie die Methode add () auf, um den Wert zu erhöhen. Es ist nicht überraschend, dass die beiden Instanzen unabhängig voneinander sind, sodass sie getrennt voneinander an Wert zunehmen. Die Quelle sieht so aus.

//Beim Benutzen

Counter cntA=new Counter();        //Erstellen Sie die Instanz cntA
System.out.println(cntA.add());        //1 wird angezeigt
System.out.println(cntA.add());        //2 wird angezeigt

Counter cntB=new Counter();        //Erstellen Sie die Instanz cntB
System.out.println(cntB.add());        //1 wird angezeigt
System.out.println(cntB.add());        //2 wird angezeigt

[Ergebnis]

1
2
1
2

Nein, das war vorher. Leicht leicht. Jeder kann dieses Mon verstehen.

damit. Das ist es. Dies ist eine Schließung.

…… e? !! Das ist? Ist das eine Schließung? "Ja wirklich?" !! Ist das das einzige? !!

damit. Das ist alles.

Kurz gesagt, (wieder) ein Abschluss ist eine Klasse (und ihre Methoden) mit nur einer Methode **. Solche Dinge werden höchstens speziell mit einem Namen wie "näher" behandelt. Ich verstehe die Welt von JavaScript nicht. [^ 3]

[^ 3]: Ich habe es geschrieben, aber das Konzept der Schließung existiert schon lange vor der Geburt von JavaScript.

Wenn Sie dies verstehen, können Sie in Java "verschiedene Dinge, die als Merkmale von Verschlüssen gelten, die Sie nicht verstehen", klar verstehen.

--Closer hat eine Funktion in der Funktion! In JavaScript gibt es (bis vor kurzem) kein Klassenschlüsselwort und wir verwenden stattdessen function (). Wenn Sie darin eine Methode (auch function ()) definieren, bedeutet dies, dass sich innerhalb der Funktion eine Funktion befindet.

Ich wundere mich ... Ist es nicht ein Mon, das absichtlich als Feature bezeichnet wird? Ich dachte oder dachte nicht. Es war genau das. .. .. ..

Ich denke, Sie können das Konzept der Schließung jetzt verstehen. e? Perfekt? mit diesem? Ja. Konzeptionell ist das alles.

Nachdem Sie das Konzept verstanden haben, werfen wir noch einmal einen Blick auf die Quelle des in JavaScript geschriebenen Abschlusses!

function createCounter() {    //Schließung, um einen Zähler zu machen
    var count=0;              //Eine Variable, die den Wert des Zählers speichert

    return function() {       //Funktionsdeklaration in Funktion
        return ++count;       //Erhöhen Sie den Wert des Zählers und kehren Sie dann zurück
    };
};

var cntA=createCounter();
console.log(cntA());
console.log(cntA());

Hmm. Ich glaube, ich verstehe ein bisschen mehr als zuvor, aber ich verstehe es immer noch nicht. .. .. Ich denke, dass. Warum ist das? Dies liegt nicht daran, dass ** das Konzept des Schließens schwierig ist, sondern an JavaScript-spezifischen Notationsproblemen **. Closures ähneln konzeptionell Java-Klassen, aber die oben genannten Quellen nutzen JavaScript-spezifische Funktionen, die Java nicht kennen:

Deshalb sieht es schwieriger aus als es wirklich ist. Dies ist auch ein hoher Schwellenwert für Java-Programmierer. Schauen wir uns das an.

Versuchen Sie, mit Javascript neu zu schreiben

Nehmen wir nun ein Beispiel für die in Java erstellte Zählerklasse, die wir zuvor gesehen haben und die "getreu" von der Java-ähnlichen Notation in JavaScript konvertiert wird.

function counter()    //Funktioniere die Klasse()ändern
{
  var count=0;         //Feld mit dem Wert des Zählers
  this.add=function()  //Methode zum Hinzufügen
  {
    count ++;          //Ich addiere den Zählerwert
    return count;      //Und zurück
  }
}

//Beim Benutzen

var cntA=new counter();    //Erstellen Sie die Instanz cntA des Abschlusses
console.log(cntA.add());   //Fügen Sie den Rückgabewert hinzu und geben Sie ihn auf dem Bildschirm aus
console.log(cntA.add());

var cntB=new counter();    //Erstellen Sie die Instanz cntB des Abschlusses
console.log(cntB.add());   //Fügen Sie den Rückgabewert hinzu und geben Sie ihn auf dem Bildschirm aus
console.log(cntB.add());

[Ergebnis]

1
2
1
2

Oh. Dies kann vom Java-Gehirn verstanden werden. Es ist wirklich "Java-ähnliches" JavaScript. Es gibt kein Problem mit dem Ausführungsergebnis.

damit. Diese Notation ist für Java-Programmierer leicht zu verstehen, aber andererseits ist sie natürlich nicht JavaScript-ähnlich. Zum Beispiel scheint das Schreiben von console.log (cntA.add ()); überflüssig. Korrekt. Hier spielt counter () eine Klassenrolle, aber wie Sie sehen können, ist es tatsächlich function (), also ist es in erster Linie eine Funktion. Wenn es darum geht, gibt es sowieso nur eine Methode, und wenn Sie console.log (cntA ()); schreiben, wird add () intern aufgerufen, ist es nicht besser? Ich denke.

Tatsächlich (dies ist der Teil, mit dem Java-Shops nicht vertraut sind) ** In JavaScript ist die Funktion ein Objekt **. Mit anderen Worten, Sie können ** die Funktion selbst einer Variablen als Wert zuweisen ** oder ** als Rückgabewert zurückgeben **. Sie sollten also "counter ()" als "eine Funktion implementieren, die die Funktion" add () "selbst zurückgibt"! Das ist (wahrscheinlich) eine JavaScript-ähnliche Idee.

Behandle die Funktion als Wert

Mal sehen, wie man eine Funktion als Wert behandelt. Das heißt, es ist keine separate Geschichte, es ist eigentlich ziemlich einfach. Insbesondere wenn Sie die Klammern am Ende der Funktion verwenden (dh wenn es sich um "add ()" handelt, schreiben Sie "add"), können Sie die Funktion als Wert behandeln.

Sie können es sofort sehen, indem Sie sich das Beispiel ansehen. Ich denke, das einfachste Beispiel sieht so aus:

//In diesem Beispiel wird Folgendes ausgeführt:
//- Weisen Sie die Funktion selbst einer Variablen zu
//- Setzen Sie Variablen in Klammern und rufen Sie die zugewiesene Funktion auf und führen Sie sie aus

function hello()    //Funktionsdefinition
{
	console.log("hello world!");    //String-Ausgabe
}

var hoge=hello;	    //Nehmen Sie Klammern und weisen Sie die Funktion selbst einer Variablen zu
hoge();	  //Sie können die zugewiesene Funktion ausführen, indem Sie nach der Variablen Klammern setzen.

var fuga=hoge;	    //Versuchen Sie, es einer anderen Variablen zuzuweisen.
fuga();  //Wenn Sie dies ebenfalls in Klammern setzen, können Sie die zugewiesene Funktion ausführen.

Ausführungsergebnis

hello world!
hello world!

Oh oh. Die Funktion ist einer Variablen als Wert zugeordnet! Es ist ein ziemlich cooler Mechanismus, ihn als Funktion ausführen zu können, indem nach der Variablen Klammern eingefügt werden.

Wenden wir dies auf das Zählerbeispiel an. Sie können es so ändern, dass beim Aufruf von "counter ()" die Funktion "add ()" ** selbst ** zurückgegeben wird.

function counter()        // add()Geben Sie die Funktion selbst zurück
{
  var count=0;        
  this.add=function()
  {
    count ++;                 
    return count;         //Gibt den Wert des Zählers zurück
  }
  return add;             // ★★★★add()Gibt die Funktion "selbst" zurück
}

//Beim Benutzen

var cntA=counter();       // add()Wird zurückgegeben und zu cntA hinzugefügt()Ist enthalten
console.log(cntA());      // add()Das Ausführungsergebnis wird angezeigt
console.log(cntA());

var cntB=counter();       // add()Ist zurück gekommen
console.log(cntB());      // add()Das Ausführungsergebnis wird angezeigt
console.log(cntB());

Wie ist das? Wir geben Funktionen als Rückgabewerte zurück und weisen sie Variablen zu! Es ist eine ziemlich JavaScript-ähnliche Quelle geworden!

Als nächstes kommt die Herausforderung anonymer Funktionen!

Sie können es jedoch tatsächlich JavaScript-ähnlicher machen. Als nächstes kommt die "anonyme Funktion".

Schauen wir uns zunächst noch einmal die obige Quelle an. Es wird "add ()" als Methode bereitgestellt, dies wird jedoch nur innerhalb von "counter ()" aufgerufen. Dann müssen Sie sich nicht die Mühe machen, ihm einen Namen wie "add" zu geben, oder? Das ist eine JavaScript-ähnliche Idee. Das ist also eine anonyme Funktion.

Dies ist dasselbe, als wenn sich nur eine andere Person als Sie im Raum befindet. Die andere Person dreht sich um, wenn Sie "das" sagen, ohne den Namen nennen zu müssen.

Übrigens gibt es in Java einige anonyme Klassen, aber wenn Sie sie zu oft verwenden ... herrscht in der Java-Welt Luft. Das Bild ist, dass Enthusiasten es mit einem schlampigen Gesicht verwenden, teilweise weil "die Lesbarkeit bei Verwendung einer anonymen Klasse abnimmt" (persönlicher Eindruck). In der Welt von JavaScript werden anonyme Funktionen jedoch ziemlich locker verwendet. Ist es ein kultureller Unterschied zwischen der Serverseite und dem Frontend? </ font>

Nun, das ist in Ordnung. Verwenden wir eine anonyme Funktion. Insbesondere werden die folgenden Teile der Quelle geändert.

  this.add=function()
  {
    count ++;                 
    return count;       //Gibt den Wert des Zählers zurück
  }
  return add;           // ★★★★add()Gibt die Funktion "selbst" zurück

Sie können die anonyme Funktion verwenden, um die obige Quelle wie folgt umzuschreiben:

  return function()     //★★★★ Schreiben Sie die Funktion, die unmittelbar nach der Rückgabe zurückgegeben werden soll
  {
    count ++;                 
    return count;       //Gibt den Wert des Zählers zurück
  }

Es ist wunderbar. Sicherlich ist " add "weg.

Es ist ein altes menschliches Gefühl wie ich, dass es weg ist, aber in der Welt von JavaScript ist so etwas ziemlich normal.

Wenn Sie erfahren, dass Sie die Funktion selbst als Rückgabewert zurückgeben können, werden Sie verstehen, dass dies der Fall ist. Wenn jedoch die tatsächlich zurückgegebene Funktion unmittelbar nach der "return" -Anweisung wie folgt definiert wird, muss sich der Java-Shop unwohl fühlen. .. ..

Das ist wahrscheinlich

	var a=5;
	return a;

Wie viel zu schreiben

	return 5;

Ist es nicht ein Gefühl, dass das Schreiben schneller ist?

Schauen wir uns noch einmal die Quelle der Schließung an

Schauen wir uns nun noch einmal die gesamte Quelle an, die die anonyme Funktion widerspiegelt.

function counter()
{
  var count=0;        
  return function()   //★★★★ Unmittelbar nach der Rückgabe wurde eine anonyme Funktion beschrieben, die zurückgegeben werden soll
  {
    count ++;                 
    return count;     //Gibt den Wert des Zählers zurück
  }
}

Beim Benutzen

var cntA=counter();   //Die anonyme Funktion selbst wird zurückgegeben und der Variablen cntA zugewiesen
console.log(cntA());  //Sie können es nennen, weil es den Namen cntA hat!
console.log(cntA());

var cntB=counter();   //Wenn Sie es einer anderen Variablen zuweisen, wird es zu einer anderen Instanz.
console.log(cntB());  //Es funktioniert unabhängig
console.log(cntB());

Beeindruckend! Zu Beginn wurde die Quelle des JavaScript-Abschlusses "Ich weiß nicht, was Sie überhaupt tun, auch wenn Sie sich das ansehen" erstellt, bevor Sie es wissen! Was war das? ** Wenn Sie eine Funktion als Wert behandeln oder eine anonyme Funktion verwenden, wird diese Art von "wirklich JavaScript!" Zur Quelle von Kanji **? Wurde gefunden wurde gefunden. Aha.

Ich werde das Ausführungsergebnis nur für den Fall schreiben. Es ist wie folgt.

1
2
1
2

Zusammenfassung auf dem Weg

Ich werde den bisherigen Inhalt kurz zusammenfassen.

――Closing ist ein Mechanismus wie "eine Klasse mit nur einer Methode" in Java.

  • Konzeptionell super einfach -Daher können Sie mehrere unabhängige Instanzen erstellen ――Der Grund, warum es seltsam schwierig schien, ist der Teil, der JavaScript eigen ist, wie die Rückgabe der Funktion selbst oder die Verwendung einer anonymen Funktion, die nichts mit dem Schließen zu tun hat. ――Ich sage es noch einmal, das Konzept der Schließung selbst ist überhaupt nicht schwierig, es ist einfach.

Was ist denn so schön an Cloja?

Selbst wenn Sie sich verschiedene Blogs ansehen, die Closure erklären, werden Sie hier landen. Aber vielleicht ist die Bedeutung anders. In einem solchen Blog und diesem Artikel.

Ich denke, dass Leute, die mit dem Programmieren von JavaScript angefangen haben, wahrscheinlich nach langer Zeit nach dem Programmieren mit der Idee von "Klassen und Instanzen" (im weiteren Sinne) in Kontakt gekommen sind. Denn in der Welt von JavaScript können Sie viel Code schreiben, der vor Ort verwendet werden kann, ohne dies zu wissen.

Ich denke, der Grund, warum diese Leute über Schließungen stolpern, ist wahrscheinlich, dass es so viele Hindernisse für das Verständnis gibt, dass Schließungen Instanzen von Funktionen sind. Zuallererst: "Was ist eine Instanz?" "Was ist das erste Wort, das Sie hören?" Und wenn Sie die Vorteile von Klasseninstanzen nicht kennen, kennen Sie die Vorteile von Schließungen nicht.

Es gibt viele Fragen auf der Welt ** "Was macht mich glücklich über das Schließen?" **, aber ich denke, die Antwort lautet ** "Es kann verstanden werden, wenn man die klassenbasierte Objektorientierung versteht" **. Persönlich denke ich.

Wenn Sie dagegen mit der Programmierung von Java aus begonnen haben, sind Sie von Anfang an neu. Es gibt eine neue Klasse, eine Instanz wird erstellt und kann endlich verwendet werden. Dies ist die Struktur von Java, einer klassenbasierten objektorientierten Sprache. Wenn Sie sie also nicht verstehen, können Sie keinen Java-Code schreiben.

Im Gegenteil, wenn Sie Java verstehen, können Sie das Schließen leicht verstehen. Ich denke, es ist nur so, dass es nicht viele Leute gab, die aus der Perspektive erklärten, dass "Schließer Klassen mit nur einer Methode sind".

Also nochmal. ** Was freut dich an Cloja? ** **. Ich habe es bisher geschrieben, aber ich denke, dass sogar Java-Shops diese Frage haben könnten. Es ist jedoch keine Frage zu Schließungen, die in der Vergangenheit gesagt wurde, sondern es bedeutet "Ist es nicht in Ordnung mit einer Klasse, nicht mit einer Schließung?"

Denken Sie nach dem bisherigen Inhalt nicht: "Nein, dann sollten Sie die Klasse normal anstelle des Abschlusses verwenden?" Tatsächlich ist der Abschluss die verschlechterte Version der Klasseninstanz selbst (dh mit der Einschränkung nur einer Methode). [^ 2]

[^ 2]: Ich denke, es gibt verschiedene Dinge wie "Ich mag das nicht, ist es nicht genau eine Klasse?", Aber das weicht vom Zweck des Artikels ab.

Ich behandle es wie einen besonders bequemen und schwierigen Mechanismus und verstehe es überhaupt nicht. Es ist super einfach, wenn man sich fragt, wie schwierig es ist, weil jeder sagt, es sei schwierig und schwierig. Ich denke, das ist der Eindruck allgemeiner Java-Programmierer.

Tatsächlich können alle Vorteile von Schließungen (die angeblich sind) gelöst werden, indem sie in einer Klasse implementiert werden. Wenn Sie es in einer Klasse implementieren, können Sie außerdem mehrere Methoden verwenden. Dieses Mal habe ich ein Beispiel für Zähler gegeben, aber wenn Sie normal denken und Zähler erstellen, möchten Sie möglicherweise nicht nur die Anzahl erhöhen, sondern auch die Zähler zurücksetzen und in einigen Fällen verringern. Aber nein. Ein Verschluss kann nur eine Methode haben. Wenn dies der Fall ist, ist es nicht besser, die Klasse von Anfang an zu verwenden, als den Abschluss zu verwenden? Ich denke, es gibt viele Leute, die das denken

Dies ist richtig. Es ist ein individueller Eindruck, aber vielleicht ist dies ein Unterschied in den Werten.

In der Java-Welt ist es natürlich, Klassen zu erstellen. Oder besser gesagt, das ist die einzige Option. In der Welt von JavaScript können Sie jedoch Klassen oder Abschlüsse erstellen. Wenn ja, denke ich, dass es eine einfache Person ist, aber "einfach" ist subjektiv. Ich denke, dass es in der Welt von JavaScript eine ganze Reihe von Menschen gibt, die das Gefühl haben, dass es schwierig ist, eine Klasse zu erstellen, oder die nicht wissen, was eine Klasse überhaupt ist, geschweige denn, wie man sie erstellt. Ich werde.

Eine andere Sache, die ich sagen kann, ist, dass sich die Welt von JavaScript im Wesentlichen um function () dreht.

Erstens denke ich, dass JavaScript von "einem Mechanismus zur Beschreibung der Rückrufverarbeitung stammt, die ausgeführt wird, wenn eine bestimmte Schaltfläche gedrückt wird". Wenn Sie beispielsweise versuchen, einen einfachen Mechanismus zu implementieren, der den Inhalt überprüft, indem Sie die JavaScript-Funktion aufrufen, wenn Sie auf die Schaltfläche klicken (obwohl ich nicht viel gesehen habe, weil diese Schreibweise heutzutage nicht beliebt ist) Es steht geschrieben.

 <input type="button" name="submitButton" value="hinzufügen" onClick="checkInput();">

Der Teil von onClick =" checkInput (); ", was bedeutet "wenn diese Schaltfläche angeklickt wird, wird die JavaScript-Funktion checkInput (); aufgerufen ".

Wenn Sie es sich ansehen, können Sie die Atmosphäre sehen, aber es ist etwas ungeeignet, die Tatsache zu beschreiben, dass es sich hier um eine Klasse oder eine Instanz handelt.

In letzter Zeit wird auch jQuery für einen solchen Teil verwendet, aber wenn Sie hier eine Rückruffunktion implementieren, schreiben Sie sie wie folgt.

$(function(){
	var pushed=false;   //Noch nicht gedrückt
	$('#button').on('click', function() {
		if(pushed===false)
		{
			pushed=true;   //Es wurde geschoben!
			submit();      //einreichen
		} else {           //Verhindert zweimaliges Senden
			alert('Hast du es schon gedrückt?');
		}
	})
})

Dies ist auch eine Art Abschluss, aber auf einer solchen Framework-Ebene wird "Nein, ich möchte es in einer Klasse implementieren!" Überhaupt nicht berücksichtigt. Ich glaube nicht, dass Sie es nicht in einer Klasse schreiben können, aber wie implementieren Sie es? Ich denke einen Moment nach. Wenn ja, ist es einfacher, den Verschluss zu verwenden? Ich denke. Ist es eine Frage der Vertrautheit? Ist es?

Fazit

damit,

  • Croja war eigentlich einfach »Aber manchmal denke ich, es wäre besser, es in einer Klasse zu implementieren. ――Das Schließen ist jedoch möglicherweise besser für das Verschieben auf einer Webseite geeignet

Ist das der Ort? Wie ist das?

Ich hoffe, Java-Programmierer können jetzt Schließungen verstehen.

Denken Sie nicht, dass JavaScript ziemlich interessant ist? Ich denke, das ist eine tiefe Welt. Mit SPA (Single-Page Application) werden Webseiten weiterhin angezeigt und haben einen Status, anstatt jedes Mal weggeworfen zu werden, wenn sich der Bildschirm ändert. In diesem Fall denke ich, dass ein Sinn erforderlich sein wird, der sich völlig von der herkömmlichen JavaScript-Programmierung unterscheidet, aber eher der serverseitigen Programmierung nahe kommt. Sie müssen auch Klassen und Objekte schreiben. Wird das in Java gepflegte Gefühl nicht wirklich gebraucht? Ich denke.

Ist es nicht interessant, diese Gelegenheit zu nutzen, um ernsthaft JavaScript zu studieren?

Recommended Posts

[JavaScript] Java-Programmierer! Sie können das Schließen von JavaScript sehr leicht verstehen!
Probleme, die leicht mit Java und JavaScript verwechselt werden können
[Java] Können Sie dieses Phänomen erklären?
Kannst du es machen? Java EE
[Java] Einführung des Dienstprogramms "ZT Zip", das ZIP-Dateien sehr einfach verarbeiten kann
[Gute Nachrichten] Sie können immer noch mit Java 8 gehen !!
Scala impliziert, dass sogar Java-Shops verstehen können