Ten kod zawsze działa, nawet w różnych przeglądarkach:
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();
Nie mogłem jednak znaleźć ani jednej wzmianki o tym, dlaczego to powinno działać. Po raz pierwszy zobaczyłem to w notatce prezentacyjnej Johna Resiga, ale zostało tylko wspomniane. Nie ma żadnego wyjaśnienia tej sprawy.
Czy ktoś mógłby mnie oświecić?
javascript
function
Edu Felipe
źródło
źródło
Odpowiedzi:
function
Deklaracja jest magia i powoduje jego identyfikator na związanie zanim cokolwiek w swoim bloku kodu * jest wykonywany.Różni się to od przypisania z
function
wyrażeniem, które jest oceniane w normalnej kolejności odgórnej.Jeśli zmieniłeś przykład, aby powiedzieć:
przestanie działać.
Deklaracja funkcji jest syntaktycznie całkiem odrębna od wyrażenia funkcyjnego, mimo że wyglądają prawie identycznie i mogą być w niektórych przypadkach niejednoznaczne.
Jest to udokumentowane w standardzie ECMAScript , sekcja 10.1.3 . Niestety ECMA-262 nie jest bardzo czytelnym dokumentem, nawet według standardów!
*: zawierająca funkcję, blok, moduł lub skrypt.
źródło
Nazywa się to PODNOSZENIE - wywołanie (wywołanie) funkcji przed jej zdefiniowaniem.
Dwa różne typy funkcji, o których chcę napisać to:
Funkcje wyrażeń i funkcje deklaracji
Funkcje wyrażeń:
Wyrażenia funkcyjne mogą być przechowywane w zmiennej, więc nie potrzebują nazw funkcji. Zostaną również nazwane jako funkcja anonimowa (funkcja bez nazwy).
Aby wywołać (wywołać) te funkcje, zawsze potrzebują nazwy zmiennej . Ten rodzaj funkcji nie będzie działał, jeśli zostanie wywołany przed zdefiniowaniem, co oznacza, że podnoszenie nie ma tutaj miejsca. Zawsze musimy najpierw zdefiniować funkcję wyrażenia, a następnie ją wywołać.
Oto jak możesz to zapisać w ECMAScript 6:
Funkcje deklaracji:
Funkcje zadeklarowane za pomocą następującej składni nie są wykonywane natychmiast. Są „zapisywane do późniejszego wykorzystania” i będą wykonywane później, kiedy zostaną wywołane (przywołane). Ten typ funkcji działa, jeśli wywołasz ją PRZED lub PO, gdzie zostało zdefiniowane. Jeśli wywołasz funkcję deklaracji, zanim została zdefiniowana, funkcja podnoszenia działa poprawnie.
Przykład podnoszenia:
źródło
let fun = theFunction; fun(); function theFunction() {}
będzie również działać (węzeł i przeglądarki)Przeglądarka odczytuje kod HTML od początku do końca i może go wykonać, gdy jest odczytywany i parsowany na fragmenty wykonywalne (deklaracje zmiennych, definicje funkcji itp.) Ale w dowolnym momencie może używać tylko tego, co zostało zdefiniowane w skrypcie przed tym punktem.
Różni się to od innych kontekstów programowania, które przetwarzają (kompilują) cały kod źródłowy, być może łączą go z dowolnymi bibliotekami potrzebnymi do rozwiązywania odwołań i konstruują moduł wykonywalny, w którym rozpoczyna się wykonywanie.
Twój kod może odwoływać się do nazwanych obiektów (zmiennych, innych funkcji itp.), Które są zdefiniowane w dalszej części, ale nie możesz wykonać kodu odsyłającego, dopóki wszystkie elementy nie będą dostępne.
Kiedy zaznajomisz się z JavaScriptem, staniesz się dokładnie świadomy swojej potrzeby pisania rzeczy we właściwej kolejności.
Rewizja: Aby potwierdzić zaakceptowaną odpowiedź (powyżej), użyj Firebuga, aby przejść przez sekcję skryptów na stronie internetowej. Zobaczysz, jak przeskakuje od funkcji do funkcji, odwiedzając tylko pierwszą linię, zanim faktycznie wykona jakikolwiek kod.
źródło
Niektóre języki wymagają zdefiniowania identyfikatorów przed użyciem. Powodem tego jest to, że kompilator używa pojedynczego przebiegu w kodzie źródłowym.
Ale jeśli jest wiele przepustek (lub niektóre czeki są odkładane), możesz doskonale żyć bez tego wymogu. W tym przypadku kod jest prawdopodobnie najpierw czytany (i interpretowany), a następnie ustawiane są linki.
źródło
Użyłem JavaScript tylko trochę. Nie jestem pewien, czy to pomoże, ale wygląda bardzo podobnie do tego, o czym mówisz i może dać pewien wgląd:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
źródło
Ciało funkcji „internalFoo” musi gdzieś trafić w czasie analizy, więc kiedy kod jest odczytywany (czyli parsowany) przez interpreter JS, tworzona jest struktura danych funkcji i przypisywana jest jej nazwa.
Dopiero później, po uruchomieniu kodu, JavaScript faktycznie próbuje dowiedzieć się, czy „internalFoo” istnieje i co to jest i czy można go wywołać itp.
źródło
Z tego samego powodu
foo
w globalnej przestrzeni nazw zawsze będą umieszczane :źródło
if
Blok nie tworzy zakres, natomiastfunction()
blok zawsze tworzy jeden. Prawdziwym powodem było to, że definicja globalnych nazw javascript odbywa się na etapie kompilacji, więc nawet jeśli kod nie działa, nazwa jest definiowana. (Przepraszam, że tak długo trwało komentowanie)