Home » Uncategorized » JavaScript – Functions Scope / This

JavaScript – Functions Scope / This

Contents

Closures – Function Scope

Mit einer Funktion lässt sich so etwas wie eine Klassendefinition erstellen. Wird von der Funktion eine (eingebettete) Funktion zurückgegeben, dann hat diese den ganzen scope ihrer umgebenden Funktion erhalten:

function remember(number){
   return function(){
      return number;
   }
}
f1 = remember(99);
f1();
//99

Vorsicht bei Übergabe von Funktionen!!

Im Gegensatz zu Java können Funktionen manchmal ‚Instanz-Variablen‘ haben, manchmal aber auch nicht. Auf was die This-Referenz der Funktion zeigt kann verwirrend unterschiedlich sein.
Im obigen Beispiel ist f1 eine „Objekt-Funktion“, d.h. eine Funktion mit einem Funktionspezifischen Scope (Java-Entwickler würden von einer Instanz sprechen).

Keinen non-global Closure hat hingegen eine Funktion, die zwar innerhal eines Objektes definiert ist, die aber dann (ohne umgebendes Objekt) als Referenz über geben wird:

> const dog = {
... age: 5,
... growOneYear: function(){
..... this.age += 1;
..... }
};
undefined
> dog.growOneYear();
undefined
> dog.age;
6
> function invokeTwice(cb){
... cb();
... cb();
}
undefined
> invokeTwice(dog.growOneYear);
undefined
> dog.age;
6 //<-- Hinaufzählen hat nicht funktioniert!

Wie man sieht hat die Funktionsreferenz dog.growOneYear das age Feld nicht in seinem Scope mit genommen!

Anders sieht es wiederum aus, wenn man eine Funktion mitgiebt, die durch eine andere Funktion erstellt wurde und deshalb deren Scope mit sich mit schleppt:

/* Hauptfunktion wird aufgerufen und gibt Unterfunktion zurück, die aber den Clusure hat der den Block der Hauptfunktion umfasst! */
> let catGrows = function(){
... age = 0;
... return () => {return age++;}
}(); 
undefined
> catGrows()
0
> catGrows()
1
> catGrows()
2
> invokeTwice(catGrows) /* Keine Ausgabe, aber intern wird gezählt */
undefined
> catGrows()
5
>

Das Beispiel mit dem „Function-in-Funktion-Scope“ funktioniert. Nur ist es äuserst unpraktisch, das man nur genau über eine Funktion zugriff auf das Objekt hat.

Nur wenn die Funktion auf dem Objekt aufgerufen wird, zeigt ihr This auf das Objekt:
>dog.growOneYear()

Damit invokeTwice das richtige Resultat liefert können wir auch programmieren:

> dog.age;
6
> invokeTwice(function(){dog.growOneYear();});
undefined
> dog.age;
8

gowOneYear operiert so immer auf dem mitgegebenen dog Objekt.



Die vielversprechendere Lösung ist es, via bind() Methode, der Funktion explizit das Objekt mitzugeben, auf das die This-Referenz der Funktion zeigen soll:



> objectBoundGrowOneYearFunction = dog.growOneYear.bind(dog);
[Function: bound growOneYear]
> invokeTwice(objectBoundGrowOneYearFunction);
undefined
> dog.age;
10
>

Hinterlasse einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert