it-swarm.com.de

Warum kann ich eine Funktion verwenden, bevor sie in JavaScript definiert ist?

Dieser Code funktioniert immer, auch in verschiedenen Browsern:

function fooCheck() {
  alert(internalFoo()); // We are using internalFoo() here...

  return internalFoo(); // And here, even though it has not been defined...

  function internalFoo() { return true; } //...until here!
}

fooCheck();

Ich konnte jedoch keinen einzigen Hinweis darauf finden, warum es funktionieren sollte. Ich habe das zum ersten Mal in John Resigs Präsentationsnotiz gesehen, aber es wurde nur erwähnt. Es gibt keine Erklärung für diese Angelegenheit.

Könnte mich bitte jemand aufklären?

151
Edu Felipe

Die function -Deklaration ist magisch und bewirkt, dass sein Bezeichner gebunden wird, bevor etwas in seinem Code-Block * ausgeführt wird.

Dies unterscheidet sich von einer Zuweisung mit einem Ausdruck function, der in normaler Reihenfolge von oben nach unten ausgewertet wird.

Wenn Sie das Beispiel geändert haben, um Folgendes zu sagen:

var internalFoo = function() { return true; };

es würde aufhören zu funktionieren.

Die Funktionsdeklaration unterscheidet sich syntaktisch deutlich vom Funktionsausdruck, obwohl sie fast identisch aussieht und in einigen Fällen mehrdeutig sein kann.

Dies ist im ECMAScript-Standard , Abschnitt 10.1.3 dokumentiert. Leider ist ECMA-262 auch für Standards kein sehr lesbares Dokument!

*: die enthaltende Funktion, Block, Modul oder Skript.

203
bobince

Es heißt HOISTING - Rufe eine Funktion auf, bevor sie definiert wurde.

Zwei verschiedene Arten von Funktionen, über die ich schreiben möchte, sind:

Ausdrucks- und Verzögerungsfunktionen

  1. Ausdrucksfunktionen:

    Ein Funktionsausdruck kann in einer Variablen gespeichert werden, sodass keine Funktionsnamen erforderlich sind. Sie werden auch als anonyme Funktion benannt (eine Funktion ohne Namen).

    Zum Aufrufen (Aufrufen) müssen sie immer einen Variablennamen verwenden. Diese Art von Funktionen funktioniert nicht, wenn zuvor Aufrufe definiert wurden, was bedeutet, dass hier kein Heben stattfindet. Wir müssen immer zuerst die Ausdrucksfunktion definieren und sie dann aufrufen.

    let lastName = function (family) {
     console.log("My last name is " + family);
    };
    let x = lastName("Lopez");
    

    So können Sie in ECMAScript 6 schreiben:

    lastName = (family) => console.log("My last name is " + family);
    
    x = lastName("Lopez");
    
  2. Verzögerungsfunktionen:

    Funktionen, die mit der folgenden Syntax deklariert sind, werden nicht sofort ausgeführt. Sie werden "zur späteren Verwendung gespeichert" und später ausgeführt, wenn sie aufgerufen (aufgerufen) werden. Diese Art von Funktionen funktioniert, wenn Sie sie VOR oder NACH ihrer Definition aufrufen. Wenn Sie eine Verzögerungsfunktion aufrufen, bevor sie definiert wurde, funktioniert das Heben ordnungsgemäß.

    function Name(name) {
      console.log("My cat's name is " + name);
    }
    Name("Chloe");
    

    Beispiel für das Heben:

    Name("Chloe");
    function Name(name) {
       console.log("My cat's name is " + name);
    }
    
19
Negin

Der Browser liest Ihren HTML-Code von Anfang bis Ende und kann ihn ausführen, während er gelesen und in ausführbare Blöcke (Variablendeklarationen, Funktionsdefinitionen usw.) zerlegt wird. Er kann jedoch zu jedem Zeitpunkt nur das verwenden, was zuvor im Skript definiert wurde.

Dies unterscheidet sich von anderen Programmierkontexten, die Ihren gesamten Quellcode verarbeiten (kompilieren), ihn möglicherweise mit Bibliotheken verknüpfen, die Sie zum Auflösen von Verweisen benötigen, und ein ausführbares Modul erstellen, mit dem die Ausführung beginnt.

Ihr Code kann auf benannte Objekte (Variablen, andere Funktionen usw.) verweisen, die weiter unten definiert sind. Sie können jedoch keinen verweisenden Code ausführen, bis alle Teile verfügbar sind.

Wenn Sie mit JavaScript vertraut sind, werden Sie sich genau darüber im Klaren sein, dass Sie die Dinge in der richtigen Reihenfolge schreiben müssen.

Revision: Um die akzeptierte Antwort (oben) zu bestätigen, verwenden Sie Firebug, um den Skriptabschnitt einer Webseite zu durchlaufen. Sie werden sehen, dass es von Funktion zu Funktion überspringt und nur die erste Zeile besucht, bevor es tatsächlich Code ausführt.

13
dkretz

Bei einigen Sprachen müssen vor der Verwendung Kennungen definiert werden. Ein Grund dafür ist, dass der Compiler einen einzelnen Durchgang für den Quellcode verwendet.

Aber wenn es mehrere Durchgänge gibt (oder einige Prüfungen verschoben werden), können Sie ohne diese Anforderung perfekt leben. In diesem Fall wird der Code wahrscheinlich zuerst gelesen (und interpretiert) und dann die Links gesetzt.

3
Toon Krijthe

Ich habe nur wenig JavaScript verwendet. Ich bin mir nicht sicher, ob dies helfen wird, aber es sieht dem, wovon Sie sprechen, sehr ähnlich und gibt möglicherweise einen Einblick:

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/

2
RailsSon

Der Rumpf der Funktion "internalFoo" muss sich zur Analysezeit irgendwo befinden. Wenn der Code vom JS-Interpreter gelesen (und analysiert) wird, wird die Datenstruktur für die Funktion erstellt und der Name zugewiesen.

Erst später, wenn der Code ausgeführt wird, versucht JavaScript herauszufinden, ob "internalFoo" existiert und was es ist und ob es aufgerufen werden kann, usw.

0
Aaron Digulla