Czytałem kilka postów na temat zamknięć i widziałem to wszędzie, ale nie ma jasnego wyjaśnienia, jak to działa - za każdym razem, gdy kazano mi go używać ...:
// Create a new anonymous function, to use as a wrapper
(function(){
// The variable that would, normally, be global
var msg = "Thanks for visiting!";
// Binding a new function to a global object
window.onunload = function(){
// Which uses the 'hidden' variable
alert( msg );
};
// Close off the anonymous function and execute it
})();
Ok, widzę, że stworzymy nową anonimową funkcję, a następnie ją uruchomimy. Po tym ten prosty kod powinien działać (i działa):
(function (msg){alert(msg)})('SO');
Moje pytanie brzmi, jaka magia się tutaj dzieje? Myślałem, że kiedy napisałem:
(function (msg){alert(msg)})
wtedy utworzona zostanie nowa nienazwana funkcja, taka jak funkcja „” (msg) ...
ale dlaczego to nie działa?
(function (msg){alert(msg)});
('SO');
Dlaczego musi znajdować się w tej samej linii?
Czy możesz podać mi jakieś posty lub wyjaśnienia?
(function (msg){alert(msg)})('SO');
działa całkowicie sama. Nie ma to nic wspólnego z inną anonimową funkcją, którą wcześniej opublikowałeś. Są to dwie całkowicie odrębne anonimowe funkcje. Musisz natychmiast wywołać funkcję anonimową, ponieważ nie ma ona nazwy i nie można się do niej później odwoływać.Odpowiedzi:
Upuść średnik po definicji funkcji.
Powyżej powinno działać.
Strona DEMO: https://jsfiddle.net/e7ooeq6m/
Omówiłem tego rodzaju wzorzec w tym poście:
jQuery i $ pytania
EDYTOWAĆ:
Jeśli spojrzysz na specyfikację skryptu ECMA , istnieją 3 sposoby zdefiniowania funkcji. (Strona 98, rozdział 13 Definicja funkcji)
1. Korzystanie z konstruktora funkcji
2. Korzystanie z deklaracji funkcji.
3. Wyrażenie funkcji
Więc możesz zapytać, jaka jest różnica między deklaracją a wyrażeniem?
Ze specyfikacji skryptu ECMA:
Jeśli zauważysz, „identyfikator” jest opcjonalny dla wyrażenia funkcji. A kiedy nie podajesz identyfikatora, tworzysz anonimową funkcję. To nie znaczy, że nie możesz podać identyfikatora.
Oznacza to, że przestrzeganie jest prawidłowe.
Ważną kwestią do zapamiętania jest to, że możesz używać „mySum” tylko w treści funkcji mySum, a nie na zewnątrz. Zobacz następujący przykład:
Demo na żywo
Porównaj to z
Uzbrojeni w tę wiedzę, spróbujmy przeanalizować Twój kod.
Kiedy masz taki kod,
Utworzyłeś wyrażenie funkcyjne. Możesz wykonać to wyrażenie wyrażeniowe, zawijając je w nawiasie.
źródło
Nazywa się to funkcją wywoływaną samodzielnie.
To, co robisz, gdy wywołujesz,
(function(){})
to zwracanie obiektu funkcji. Po dołączeniu()
do niego jest wywoływane i wykonywane jest wszystko w ciele.;
Oznacza koniec rachunku, dlatego 2nd wywołanie kończy się niepowodzeniem.źródło
Jedną z rzeczy, które uznałem za mylące, jest to, że „()” to operatory grupujące.
Oto twoja podstawowa zadeklarowana funkcja.
Dawny. 1:
Funkcje są obiektami i można je grupować. Rzućmy więc pareny wokół funkcji.
Dawny. 2:
Teraz zamiast deklarować i od razu wywoływać tę samą funkcję, możemy użyć podstawienia podstawowego, aby zadeklarować ją tak, jak ją nazywamy.
Dawny. 3)
Wreszcie, nie potrzebujemy tego dodatkowego foo, ponieważ nie używamy nazwy, aby to nazwać! Funkcje mogą być anonimowe.
Dawny. 4
Aby odpowiedzieć na twoje pytanie, wróć do Przykładu 2. Twój pierwszy wiersz deklaruje jakąś funkcję bezimienną i grupuje ją, ale jej nie wywołuje. Druga linia grupuje ciąg. Obie nic nie robią. (Pierwszy przykład Vincenta).
Ale
źródło
Funkcja anonimowa nie jest funkcją o nazwie „”. Jest to po prostu funkcja bez nazwy.
Jak każda inna wartość w JavaScript, funkcja nie potrzebuje nazwy do utworzenia. Chociaż o wiele bardziej przydatne jest powiązanie go z nazwą, tak jak z każdą inną wartością.
Ale jak każda inna wartość, czasami chcesz jej użyć bez wiązania jej z nazwą. To jest samozwoływający się wzór.
Oto funkcja i liczba, bez ograniczeń, nic nie robią i nigdy nie można ich użyć:
Musimy więc przechowywać je w zmiennej, aby móc z nich korzystać, tak jak każda inna wartość:
Możesz także użyć cukru syntetycznego, aby powiązać funkcję ze zmienną:
Ale jeśli nazywanie ich nie jest wymagane i prowadziłoby do większego zamieszania i mniejszej czytelności, możesz po prostu użyć ich od razu.
Tutaj moja funkcja i moje liczby nie są powiązane ze zmienną, ale nadal można ich używać.
Mówiąc w ten sposób, wygląda na to, że funkcja wywoływania nie ma żadnej rzeczywistej wartości. Trzeba jednak pamiętać, że ogranicznik zakresu JavaScript jest funkcją, a nie blokiem ({}).
Tak więc funkcja samo-wywołująca ma w rzeczywistości takie samo znaczenie jak blok C ++, C # lub Java. Co oznacza, że zmienna utworzona w środku nie „wycieknie” poza zakres. Jest to bardzo przydatne w JavaScript, aby nie zanieczyszczać globalnego zasięgu.
źródło
Tak właśnie działa JavaScript. Możesz zadeklarować nazwaną funkcję:
I nazwij to:
Lub możesz zadeklarować funkcję anonimową:
I nazwij to:
Lub nigdy nie możesz po prostu przypisać funkcji do nazwy:
Funkcje mogą również zwracać funkcje:
Nic nie warte jest to, że wszelkie zmienne zdefiniowane w treści „var”
make_foo
zostaną zamknięte przez każdą zwracaną funkcjęmake_foo
. Jest to zamknięcie i oznacza, że każda zmiana wartości dokonana przez jedną funkcję będzie widoczna przez inną.Umożliwia to enkapsulację informacji, jeśli chcesz:
Tak działa prawie każdy język programowania oprócz Java.
źródło
Kod, który wyświetlasz,
składają się z dwóch instrukcji. Pierwszym z nich jest wyrażenie, które zwraca obiekt funkcji (który zostanie następnie wyrzucony, ponieważ nie jest zapisywany). Drugi to wyrażenie, które daje ciąg znaków. Aby zastosować funkcję do ciągu, musisz albo przekazać ciąg jako argument do funkcji podczas jej tworzenia (co również pokazano powyżej), albo będziesz musiał faktycznie zapisać funkcję w zmiennej, abyś mógł zastosuj go później, w wolnym czasie. Tak jak:
Zauważ, że przechowując anonimową funkcję (funkcję lambda) w zmiennej, skutecznie nadajesz jej nazwę. Dlatego równie dobrze możesz zdefiniować regularną funkcję:
źródło
Podsumowując poprzednie komentarze:
gdy nie jest przypisany do zmiennej, powoduje błąd składniowy. Kod jest analizowany jako instrukcja funkcji (lub definicja), która powoduje, że nawiasy zamykające są niepoprawne składniowo. Dodanie nawiasów wokół części funkcji informuje tłumacza (i programistę), że jest to wyrażenie funkcji (lub wywołanie), jak w
Jest to funkcja samo-wywołująca, co oznacza, że jest tworzona anonimowo i uruchamia się natychmiast, ponieważ wywołanie następuje w tym samym wierszu, w którym zostało zadeklarowane. Ta funkcja wywołująca jest oznaczona znaną składnią, aby wywołać funkcję bez argumentu, oraz dodane nawiasy wokół nazwy funkcji:
(myFunction)();
.Jest składni funkcja dyskusja JavaScript dobry SO .
źródło
Ta odpowiedź nie jest ściśle związana z pytaniem, ale możesz chcieć dowiedzieć się, że tego rodzaju funkcja składniowa nie jest specyficzna dla funkcji. Na przykład zawsze możemy zrobić coś takiego:
Związane z funkcjami. Ponieważ są to obiekty dziedziczące po Function.prototype, możemy wykonywać następujące czynności:
I wiesz, nie musimy nawet otaczać funkcji nawiasami, aby je wykonać. W każdym razie, dopóki próbujemy przypisać wynik do zmiennej.
Inną rzeczą, którą możesz zrobić z funkcjami, gdy tylko je zadeklarujesz, jest wywołanie
new
nad nimi operatora i uzyskanie obiektu. Następujące są równoważne:źródło
Jest jeszcze jedna właściwość, którą ma funkcja JavaScript. Jeśli chcesz wywołać rekurencyjnie tę samą funkcję anonimową.
źródło
Rozumiem pytanie pytającego, że:
Jak działa ta magia:
Mogę się mylić. Jednak zwykłą praktyką, którą znają ludzie, jest:
Powodem jest to, że nawiasy JavaScript AKA
()
nie mogą zawierać instrukcji, a gdy parser napotka słowo kluczowe funkcji, wie, że może je parsować jako wyrażenie funkcji, a nie deklarację funkcji.Źródło: post na blogu Natychmiastowe wywołanie wyrażenia funkcyjnego (IIFE)
źródło
przykłady bez nawiasów:
(jest to jedyne prawdziwe zastosowanie void, afaik)
lub
lub
też pracować.
void
powoduje ekspresję oceny, jak również przydziału i wybuchu. ostatni pracuje~
,+
,-
,delete
,typeof
, niektóre z operatorów jednoargumentowych (void
to jeden również). nie działają++
,--
ponieważ są wymagane ze względu na zmienną.podział linii nie jest konieczny.
źródło
delete
działa. nawet z'use strict';
. to też działa:delete (3 + 4);
Jest to samo-wykonująca się funkcja anonimowa. Pierwszy zestaw nawiasów zawiera wyrażenia do wykonania, a drugi zestaw nawiasów wykonuje te wyrażenia.
Peter Michaux omawia różnicę w Ważnej parze nawiasów .
Jest to przydatna konstrukcja podczas próby ukrycia zmiennych przed nadrzędną przestrzenią nazw. Cały kod w ramach funkcji jest zawarty w prywatnym zakresie funkcji, co oznacza, że nie można w ogóle uzyskać do niego dostępu spoza funkcji, co czyni go naprawdę prywatnym.
Widzieć:
źródło
Inny punkt widzenia
Najpierw możesz zadeklarować anonimową funkcję:
Następnie nazywacie to:
Ponieważ foo = function (msg) {alert (msg);}, więc możesz zastąpić foo jako:
Ale powinieneś zawinąć całą anonimową funkcję w parę nawiasów klamrowych, aby uniknąć błędu składniowego deklarowania funkcji podczas parsowania. Potem będzie,
W ten sposób łatwo mi to zrozumieć.
źródło
Kiedy zrobiłeś:
Funkcja została wcześniej zakończona z
('SO')
powodu średnika. Jeśli tylko napiszesz:To będzie działać.
Przykład roboczy: http://jsfiddle.net/oliverni/dbVjg/
źródło
Prostym powodem, dla którego nie działa, nie jest
;
wskazanie końca funkcji anonimowej. Jest tak, ponieważ bez()
końca wywołania funkcji nie jest to wywołanie funkcji. To jest,Jeśli zadzwonisz,
result = help();
jest to wywołanie funkcji i zwróci wartość true.Jeśli zadzwonisz,
result = help;
to nie jest połączenie. Jest to zadanie, w którym pomoc jest traktowana jak dane, które mają zostać przypisane do wyniku.Zadeklarowałeś / utworzyłem anonimową funkcję przez dodanie średnika,
a następnie próbował wywołać go w innej instrukcji, używając tylko nawiasów ... Oczywiście, ponieważ funkcja nie ma nazwy, ale to nie zadziała:
Tłumacz interpretuje nawiasy w drugim wierszu jako nową instrukcję / instrukcję i dlatego nie działa, nawet jeśli zrobiłeś to w ten sposób:
Nadal nie działa, ale działa po usunięciu średnika, ponieważ interpreter ignoruje białe spacje i wózki i widzi cały kod jako jedną instrukcję.
Wniosek: wywołanie funkcji nie jest wywołaniem funkcji bez
()
końca, chyba że w określonych warunkach, takich jak wywołanie przez inną funkcję, to znaczy onload = 'help' wykona funkcję pomocy, nawet jeśli nawiasy nie zostaną uwzględnione. Wierzę, że setTimeout i setInterval również pozwalają na tego typu wywołanie funkcji, a także wierzę, że interpreter dodaje nawiasy za kulisami, które w ten sposób przywracają nas do „wywołanie funkcji nie jest wywołaniem funkcji bez nawiasów”.źródło
Jest to powszechna metoda używania anonimowej funkcji jako zamknięcia, z którego korzysta wiele struktur JavaScript.
Ta funkcja jest wywoływana automatycznie po skompilowaniu kodu.
W przypadku umieszczenia
;
w pierwszym wierszu kompilator potraktował go jako dwie różne linie. Więc nie możesz uzyskać takich samych wyników jak powyżej.Można to również zapisać jako:
Aby uzyskać więcej informacji, zapoznaj się z funkcjami JavaScript / anonimowymi .
źródło
Funkcje anonimowe to funkcje dynamicznie deklarowane w czasie wykonywania. Są one nazywane funkcjami anonimowymi, ponieważ nie mają nazwy w taki sam sposób, jak zwykłe funkcje.
Funkcje anonimowe deklarowane są za pomocą operatora funkcji zamiast deklaracji funkcji. Za pomocą operatora funkcji można utworzyć nową funkcję wszędzie tam, gdzie jest to ważne, aby wstawić wyrażenie. Na przykład możesz zadeklarować nową funkcję jako parametr do wywołania funkcji lub przypisać właściwość innego obiektu.
Oto typowy przykład nazwanej funkcji:
funkcja flyToTheMoon () {alert („Zoom! Zoom! Zoom!”); } lecieć na Księżyc(); Oto ten sam przykład utworzony jako funkcja anonimowa:
var flyToTheMoon = function () {alert („Zoom! Zoom! Zoom!”); } lecieć na Księżyc();
Aby uzyskać szczegółowe informacje, przeczytaj tutaj:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
źródło
IIFE po prostu dzieli funkcję na części i ukrywa
msg
zmienną, aby nie „zanieczyszczać” globalnej przestrzeni nazw. W rzeczywistości po prostu zachowaj prostotę i rób jak poniżej, chyba że budujesz witrynę o wartości miliarda dolarów.Możesz nazwać swoją
msg
właściwość za pomocą Wzorca modułu ujawniania, takiego jak:źródło
Anonimowe funkcje mają być jednorazową transakcją, w której definiujesz funkcję w locie, dzięki czemu generuje ona dane wyjściowe z wprowadzonego przez Ciebie sygnału wejściowego. Tyle że nie podałeś danych wejściowych. Zamiast tego napisałeś coś w drugim wierszu („SO”); - niezależna instrukcja, która nie ma nic wspólnego z funkcją. Czego oczekiwałeś? :)
źródło
var foo = function() {};
. Ale wszystko inne jest w porządku.