Wenn Sie mit dem Konzept der Instanziierung einer Klasse im objektorientierten Sinne (d. h. der Erstellung eines Objekts dieser Klasse) vertraut sind, sind Sie dem Verständnis von Closures schon sehr nahe.
Stellen Sie es sich so vor: Wenn Sie zwei Person-Objekte instanziieren, wissen Sie, dass die Klassenvariable "Name" nicht zwischen den Instanzen geteilt wird; jedes Objekt hat seine eigene "Kopie". Ähnlich verhält es sich, wenn Sie einen Abschluss erstellen, der freie Variable ('calledCount' in Ihrem Beispiel oben) ist an die 'Instanz' der Funktion gebunden.
Ich denke, Ihr konzeptioneller Sprung wird durch die Tatsache behindert, dass jede Funktion/jeder Abschluss, die/der von der warnUser-Funktion zurückgegeben wird (nebenbei: das ist eine übergeordnete Funktion ) Closure bindet 'calledCount' mit demselben Initialwert (0), während es bei der Erstellung von Closures oft sinnvoller ist, unterschiedliche Initialisierer an die übergeordnete Funktion zu übergeben, ähnlich wie bei der Übergabe unterschiedlicher Werte an den Konstruktor einer Klasse.
Nehmen wir also an, dass Sie die Sitzung des Benutzers beenden wollen, wenn "calledCount" einen bestimmten Wert erreicht hat; Sie könnten dafür unterschiedliche Werte wollen, je nachdem, ob die Anfrage aus dem lokalen Netz oder dem großen bösen Internet kommt (ja, das ist ein erfundenes Beispiel). Um dies zu erreichen, könnten Sie unterschiedliche Anfangswerte für calledCount in warnUser übergeben (z.B. -3, oder 0?).
Ein Teil des Problems in der Literatur liegt in der Nomenklatur, mit der sie beschrieben werden ("lexical scope", "free variables"). Lassen Sie sich davon nicht täuschen, Closures sind einfacher, als es den Anschein hat... prima facie ;-)