| 

.NET C# Java Javascript Exception

8
Was ergibt folgender Code? Und folgender? Die Korrekte Antwort lautet: 2 und 1. Hätten Sie das gewusst? Es ist also nicht nur ein stilistischer Unterschied, wie viele glauben. Bevor das Rätsel, warum sich die Rückgaben unterscheiden, gelöst wird, wird kurz ...

Was ergibt folgender Code?

function foo() {
 function bar() {
 return 1;
 }
 return bar();
 function bar() {
 return 2;
 }
}
alert(foo());

Und folgender?

function foo() {
 var bar = function() {
 return 1;
 }
 return bar();
 var bar = function() {
 return 2;
 }
}
alert(foo());

Die Korrekte Antwort lautet: 2 und 1.

Hätten Sie das gewusst?

Es ist also nicht nur ein stilistischer Unterschied, wie viele glauben. Bevor das Rätsel, warum sich die Rückgaben unterscheiden, gelöst wird, wird kurz auf den Unterschied zwischen den Funktionen eingegangen.

Function Declarations

function bar() {
 // ...
}

Eine Function Declaration definiert eine Funktions-Variable, welche bereits bei parse-time definiert wird. Das heißt, noch bevor der Code Schritt für Schritt durchgegangen wird. Die Reihenfolge, in welcher die Funktionen vorkommen, ist also Nebensache.

function bar() {
 alert(typeof foo); // function
 function foo() {};
}

Diese Funktion darf allerdings nicht in non-function-Blöcken wie beispielsweise einer if-Abfrage vorkommen.

function bar() {
 if (x) {
 function foo() {} // Nicht gültig
 }
}

Und außerdem wird sie dem einschließenden Scope hinzugefügt.

function bar() {
 function foo() {}
 alert(typeof foo); // function
}
alert(typeof foo) // undefined

Function Expressions

var bar = function() {
 // ...
}

Eine Function Expression oder auch anonyme Funktion wird bei run-time definiert, somit erst wenn der Code Schritt für Schritt durchgegangen wird. Anonym aus dem Grund, da die Funktion keinen Namen besitzt.

function bar() {
 alert(typeof foo); // undefined
 var foo = function() {};
 alert(typeof foo); // function
}

Eine solche Funktion hat keine Einschränkung und kann in nahezu jedem Block verwendet werden.

function bar() {
 var foo;
 if (x) {
 foo = function() {} // gültig
 }
}

Es gibt auch eine Möglichkeit diese anonymen Funktionen zu benennen:

var bar = function bar() {
 // ...
}

Allerdings wird strengstens davon abgeraten, da manche Browser aufgrund von Implementierungsbugs ihre Probleme damit haben.

Zurück zum Rätsel

Der Grund, warum beim ersten Beispiel 2 zurückgegeben wird, ist im Prinzip ganz einfach: Die Funktionen werden vom JavaScript Interpreter ganz nach oben verschoben - immer im aktuellen Scope versteht sich.

Das ergibt folgenden Ablauf:

function foo() {
 function bar() {
 return 1;
 }
 // Wurde nach oben verschoben.
 function bar() {
 return 2;
 }
 return bar();
}
alert(foo());

Jetzt stellt sich die Frage, warum dies im zweiten Beispiel nicht auch der Fall ist: Werden Funktions-Variablen nicht verschoben?
Doch, allerdings werden nur die Variablen-Deklarationen und nicht deren Expressions verschoben. Soll heißen, wenn bar anfänglich verschoben wird, wird dessen Wert auf undefined gesetzt.

function foo() {
 var bar = undefined;
 var bar = undefined;
 // Die Expression bleibt an ihrer Stelle
 bar = function() {
 return 1;
 }
 return bar();
 bar = ...
}
alert(foo());

Mehr Infos über das verschieben (Auch Hoisting genannt), gibt es in einem Blogpost von Ben Cherry.

Fazit: It depends

Es gibt keine Faustregel welche der beiden Funktions-Arten nun immer eingesetzt werden sollten. Wenn die Funktion immer einen Namen haben muss, kann die Declarations Variante verwendet werden. Die Interpreter Optimierung, bzw. Verschiebung (Hoisting) bringt nicht wirklich viel, denn es hat einen bestimmten Grund, dass der Entwickler die Zeilen in einer gewissen Reihenfolge schreibt. Function Expressions können nahezu überall verwendet werden, während die Function Declarations nicht innerhalb von bestimmten Bereichen wie if-Abfragen stehen dürfen. Also doch nur eine Frage des Stils?

Als ich neulich mit Golo Roden darüber diskutiert habe, ist es eigentlich bad-practice die Variablen nicht ganz am Anfang zu deklarieren. Im Großen und Ganzen schließe ich mich Golo an und bevorzuge etwas mehr die Function Expressions, da man bei diesen sofort weiß, wo sie hingehören.

Note: There is a rating embedded within this post, please visit this post to rate it.
javascript
Schreibe einen Kommentar:
Themen:
javascript
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail