Dokładam wszelkich starań, aby owinąć głowę wokół zamknięć JavaScript.
Rozumiem to, zwracając funkcję wewnętrzną, będzie ona miała dostęp do dowolnej zmiennej zdefiniowanej w jej bezpośrednim obiekcie nadrzędnym.
Gdzie to by mi się przydało? Być może jeszcze nie mam wokół tego głowy. Większość przykładów, które widziałem online , nie zawiera żadnego kodu z prawdziwego świata, tylko niejasne przykłady.
Czy ktoś może mi pokazać zamknięcie?
Czy to na przykład?
var warnUser = function (msg) {
var calledCount = 0;
return function() {
calledCount++;
alert(msg + '\nYou have been warned ' + calledCount + ' times.');
};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Odpowiedzi:
Użyłem zamknięć do robienia takich rzeczy jak:
Jak widać,
a
jest teraz obiektem z metodąpublicfunction
(a.publicfunction()
), która wywołujeprivatefunction
, która istnieje tylko w zamknięciu. NIE możesz dzwonićprivatefunction
bezpośrednio (tj.a.privatefunction()
), Po prostupublicfunction()
.To minimalny przykład, ale może widzisz zastosowania? Wykorzystaliśmy to do wymuszenia metod publicznych / prywatnych.
źródło
Załóżmy, że chcesz policzyć, ile razy użytkownik kliknął przycisk na stronie internetowej.
W tym celu uruchamiasz funkcję przy
onclick
zdarzeniu przycisku, aby zaktualizować liczbę zmiennychTeraz może istnieć wiele podejść, takich jak:
1) Możesz użyć zmiennej globalnej i funkcji, aby zwiększyć licznik :
Ale pułapką jest to, że każdy skrypt na stronie może zmienić licznik bez wywoływania
updateClickCount()
.2) Teraz możesz myśleć o zadeklarowaniu zmiennej wewnątrz funkcji:
Ale hej! Po każdym
updateClickCount()
wywołaniu funkcji licznik jest ponownie ustawiany na 1.3) Myślisz o funkcjach zagnieżdżonych ?
Funkcje zagnieżdżone mają dostęp do zakresu „nad nimi”.
W tym przykładzie funkcja wewnętrzna
updateClickCount()
ma dostęp do zmiennej licznika w funkcji nadrzędnejcountWrapper()
Mogłoby to rozwiązać dylemat przeciwnika, gdybyś mógł dotrzeć do
updateClickCount()
funkcji z zewnątrz, a także znaleźć sposób na wykonaniecounter = 0
tylko raz, nie za każdym razem.4) Zamknięcie na ratunek! (funkcja auto-wywoływania) :
Funkcja auto-wywoływania działa tylko raz. Ustawia
counter
zero (0) i zwraca wyrażenie funkcji.Tą drogą
updateClickCount
staje się funkcją. „Wspaniałą” częścią jest to, że może uzyskać dostęp do licznika w zakresie nadrzędnym.Nazywa się to zamknięciem JavaScript . Umożliwia funkcji posiadającej „ prywatna zmiennych ”.
The
counter
Jest chronione przez zakres funkcji anonimowej, i może być zmieniona jedynie za pomocą funkcji dodawania!Bardziej żywy przykład zamknięcia:
Odniesienie: https://www.w3schools.com/js/js_function_closures.asp
źródło
Podany przykład jest doskonały. Zamknięcia są mechanizmem abstrakcji, który pozwala bardzo dokładnie rozdzielić obawy. Twój przykład to przypadek oddzielenia instrumentacji (liczenia wywołań) od semantyki (interfejs API do zgłaszania błędów). Inne zastosowania obejmują:
Przekazywanie sparametryzowanego zachowania do algorytmu (klasyczne programowanie wyższego rzędu):
Symulowanie programowania obiektowego:
Implementowanie egzotycznej kontroli przepływu, takiej jak obsługa zdarzeń jQuery i interfejsy API AJAX.
źródło
int
?) Ostatnio sprawdziłem, JavaScript był językiem pisanym kaczym językiem. Może myślałeś o Javie?Wiem, że spóźniłem się z odpowiedzią na to pytanie, ale może to pomóc każdemu, kto nadal szuka odpowiedzi w 2018 roku.
Zamknięć JavaScript można używać do implementacji funkcji przepustnicy i usuwania błędów w aplikacji.
Ograniczanie :
Ograniczanie ogranicza maksymalną liczbę wywołań funkcji w czasie. Jak w „wykonaj tę funkcję co najwyżej raz na 100 milisekund”.
Kod :
Ogłaszając :
Debugowanie nakłada limit na funkcję, która nie będzie wywoływana ponownie, dopóki nie upłynie określony czas bez jej wywołania. Jak w „wykonaj tę funkcję tylko wtedy, gdy minęło 100 milisekund bez wywołania”.
Kod:
Jak widać zamknięcia pomogły we wdrożeniu dwóch pięknych funkcji, które każda aplikacja internetowa powinna zapewniać płynne działanie interfejsu użytkownika.
Mam nadzieję, że to komuś pomoże.
źródło
Tak, to dobry przykład przydatnego zamknięcia. Wywołanie warnUser tworzy
calledCount
zmienną w swoim zakresie i zwraca anonimową funkcję zapisaną wwarnForTamper
zmiennej. Ponieważ nadal występuje zamknięcie wykorzystujące zmienną wywoływanąCount, nie jest ona usuwana po wyjściu z funkcji, więc każde wywołaniewarnForTamper()
i zaalarmuje wartość.Najczęstszym problemem, jaki widzę na StackOverflow, jest to, że ktoś chce „opóźnić” użycie zmiennej, która jest zwiększana w każdej pętli, ale ponieważ zakres zmiennej jest zmienny, każde odwołanie do zmiennej będzie po zakończeniu pętli, w wyniku czego stan końcowy zmiennej:
Spowodowałoby to, że każdy alert pokazywałby tę samą wartość
i
, do której został zwiększony, gdy pętla się kończy. Rozwiązaniem jest utworzenie nowego zamknięcia, oddzielnego zakresu dla zmiennej. Można to zrobić za pomocą natychmiast wykonanej funkcji anonimowej, która odbiera zmienną i przechowuje jej stan jako argument:źródło
W szczególności w języku JavaScript (lub dowolnym języku ECMAScript) zamknięcia są przydatne do ukrywania implementacji funkcjonalności, a jednocześnie ujawniają interfejs.
Wyobraź sobie na przykład, że piszesz klasę metod narzędzia daty i chcesz umożliwić użytkownikom wyszukiwanie nazw dni powszednich według indeksu, ale nie chcesz, aby mogli oni modyfikować tablicę nazw używanych pod maską.
Zauważ, że
days
tablica może być po prostu przechowywana jako właściwośćdateUtil
obiektu, ale wtedy byłaby widoczna dla użytkowników skryptu, a nawet mogliby ją zmienić, gdyby chcieli, nawet nie potrzebując kodu źródłowego. Ponieważ jednak jest on zawarty w funkcji anonimowej, która zwraca funkcję wyszukiwania daty, jest dostępny tylko dla funkcji wyszukiwania, więc jest teraz odporny na manipulacje.źródło
Jest sekcja na praktyczne Zamknięcia na Mozilla Developer Network .
źródło
return function ()...
kod, nadal działa dobrze. Zamknięcie nie jest konieczneInnym powszechnym zastosowaniem zamknięć jest powiązanie
this
metody z konkretnym obiektem, co pozwala na wywołanie go w innym miejscu (np. Jako moduł obsługi zdarzeń).Zawsze
watcher.follow(evt)
wywoływane jest zdarzenie myszy, które jest uruchamiane .Zamknięcia są również istotną częścią funkcji wyższego rzędu, umożliwiając bardzo powszechny wzór przepisywania wielu podobnych funkcji jako pojedynczej funkcji wyższego rzędu poprzez parametryzowanie odmiennych części. Jako abstrakcyjny przykład
staje się
gdzie A i B nie są jednostkami składniowymi, ale ciągami kodu źródłowego (nie literałami ciągów).
Zobacz konkretny przykład w „ Usprawnianie mojego JavaScript z funkcją ”.
źródło
Mam pozdrowienie, które chcę powiedzieć kilka razy. Jeśli utworzę zamknięcie, mogę po prostu wywołać tę funkcję, aby nagrać powitanie. Jeśli nie utworzę zamknięcia, muszę podawać swoje imię za każdym razem.
Bez zamknięcia ( https://jsfiddle.net/lukeschlangen/pw61qrow/3/ ):
Z zamknięciem ( https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/ ):
źródło
Jeśli nie masz pojęcia o tworzeniu instancji klasy w sensie obiektowym (tj. W celu stworzenia obiektu tej klasy), to jesteś blisko zrozumienia zamknięcia.
Pomyśl o tym w ten sposób: kiedy tworzysz dwa obiekty Person, wiesz, że zmienna elementu klasy „Name” nie jest współużytkowana między instancjami; każdy obiekt ma własną „kopię”. Podobnie, po utworzeniu zamknięcia, wolna zmienna (w powyższym przykładzie „o nazwie Count”) jest powiązana z „instancją” funkcji.
Myślę, że twój skok pojęciowy jest nieco utrudniony przez fakt, że każda funkcja / zamknięcie zwracane przez funkcję warnUser (na bok: to jest funkcja wyższego rzędu ) zamknięcie wiąże „wywoływane” z tą samą wartością początkową (0), podczas gdy często podczas tworzenia zamknięć bardziej przydatne jest przekazywanie różnych inicjatorów do funkcji wyższego rzędu, podobnie jak przekazywanie różnych wartości do konstruktora klasy.
Załóżmy więc, że gdy „wywoływane” osiągnie określoną wartość, którą chcesz zakończyć sesję użytkownika; możesz chcieć dla tego różnych wartości w zależności od tego, czy żądanie przychodzi z sieci lokalnej, czy z dużego złego Internetu (tak, to wymyślony przykład). Aby to osiągnąć, możesz przekazać różne wartości początkowe dla wywoływanej wartości do warnUser (tj. -3 lub 0?).
Częścią problemu z literaturą jest nomenklatura stosowana do ich opisu („zakres leksykalny”, „zmienne swobodne”). Nie daj się zwieść, zamknięcia są prostsze niż się wydaje ... prima facie ;-)
źródło
Tutaj mam jeden prosty przykład koncepcji zamknięcia, z której możemy skorzystać w naszej witrynie e-commerce lub w wielu innych. Dodaję mój link jsfiddle z przykładem. zawiera małą listę produktów składającą się z 3 produktów i jednego licznika koszyka.
Jsfiddle
źródło
Zastosowanie zamknięć:
Zamknięcia są jedną z najpotężniejszych funkcji JavaScript. JavaScript pozwala na zagnieżdżanie funkcji i zapewnia funkcji wewnętrznej pełny dostęp do wszystkich zmiennych i funkcji zdefiniowanych w funkcji zewnętrznej (i wszystkich innych zmiennych i funkcji, do których ma dostęp funkcja zewnętrzna). Jednak funkcja zewnętrzna nie ma dostępu do zmiennych i funkcji zdefiniowanych w funkcji wewnętrznej. Zapewnia to rodzaj bezpieczeństwa dla zmiennych funkcji wewnętrznej. Ponadto, ponieważ funkcja wewnętrzna ma dostęp do zakresu funkcji zewnętrznej, zmienne i funkcje zdefiniowane w funkcji zewnętrznej będą żyły dłużej niż sama funkcja zewnętrzna, jeśli funkcja wewnętrzna zdoła przetrwać poza życiem funkcji zewnętrznej.
Przykład:
W powyższym kodzie zmienna nazwy funkcji zewnętrznej jest dostępna dla funkcji wewnętrznych i nie ma innego sposobu na uzyskanie dostępu do zmiennych wewnętrznych poza funkcjami wewnętrznymi. Wewnętrzne zmienne funkcji wewnętrznej pełnią funkcję bezpiecznego magazynu funkcji wewnętrznych. Przechowują „trwałe”, ale bezpieczne dane do pracy z funkcjami wewnętrznymi. Funkcje nie muszą nawet być przypisane do zmiennej ani mieć nazwy. przeczytaj tutaj, aby poznać szczegóły
źródło
Podoba mi się przykład fabryki funkcji Mozilli .
źródło
Wzorzec modułu JavaScript używa zamknięć. Jego ładny wzór pozwala mieć coś podobnego do „publicznego” i „prywatnego”.
źródło
Niedawno napisałem artykuł o tym, jak można użyć zamknięć, aby uprościć kod obsługi zdarzeń. Porównuje obsługę zdarzeń ASP.NET z jQuery po stronie klienta.
http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/
źródło
Ten wątek ogromnie pomógł mi lepiej zrozumieć, jak działają zamknięcia. Od tego czasu przeprowadziłem własne eksperymenty i opracowałem dość prosty kod, który może pomóc innym osobom zobaczyć, w jaki sposób zamknięcia mogą być używane w praktyczny sposób i jak używać zamknięcia na różnych poziomach, aby zachować zmienne podobne do statycznych i / lub zmienne globalne bez ryzyka ich nadpisania lub pomylenia ze zmiennymi globalnymi. Pozwala to śledzić kliknięcia przycisków, zarówno na poziomie lokalnym dla każdego przycisku, jak i na poziomie globalnym, licząc każde kliknięcie przycisku, przyczyniając się do uzyskania pojedynczej liczby. Uwaga: Nie użyłem do tego żadnych zmiennych globalnych, co jest w pewnym sensie ćwiczeniem - posiadanie modułu obsługi, który można zastosować do dowolnego przycisku, który również przyczynia się do czegoś globalnie.
Proszę ekspertów, dajcie mi znać, jeśli popełniłem tutaj jakieś złe praktyki! Nadal sam się tego uczę.
źródło
Odniesienie: Praktyczne zastosowanie zamknięć
W praktyce zamknięcia mogą tworzyć eleganckie projekty, pozwalające na dostosowanie różnych obliczeń, odroczonych połączeń, oddzwaniania, tworzenia zamkniętego zakresu itp.
Przykład metody sortowania tablic, która przyjmuje jako argument funkcję warunku sortowania:
Mapowanie funkcjonałów jako metoda mapowania tablic, która mapuje nową tablicę pod warunkiem argumentu funkcjonalnego:
Często wygodnie jest zaimplementować funkcje wyszukiwania za pomocą argumentów funkcjonalnych określających prawie nieograniczone warunki wyszukiwania:
Możemy również zauważyć zastosowanie funkcji funkcjonalnych, na przykład metody forEach, która stosuje funkcję do tablicy elementów:
Funkcja jest stosowana do argumentów (do listy argumentów - w zastosowaniu i argumentów pozycjonowanych - w wywołaniu):
Odroczone połączenia:
Funkcje oddzwaniania:
Tworzenie enkapsulowanego zakresu w celu ukrycia obiektów pomocniczych:
źródło
Skrzypce
źródło
Zamknięcia są użytecznym sposobem tworzenia generatory, sekwencja zwiększana na żądanie:
Różnice podsumowano w następujący sposób:
Bibliografia
źródło
W podanej próbce wartość zawartej zmiennej „licznik” jest chroniona i można ją zmienić tylko przy użyciu podanych funkcji (przyrost, spadek). ponieważ jest w zamknięciu,
źródło
Wyjaśnienie praktycznego zastosowania Zamknięcia w JavaScript ---
Kiedy tworzymy funkcję wewnątrz innej funkcji, tworzymy zamknięcie. Zamknięcia są potężne, ponieważ są w stanie odczytywać i przetwarzać dane jego funkcji zewnętrznych. Za każdym razem, gdy wywoływana jest funkcja, tworzony jest nowy zakres dla tego wywołania. Zmienna lokalna zadeklarowana w funkcji należy do tego zakresu i można do niej uzyskać dostęp tylko z tej funkcji. Gdy funkcja zakończy wykonywanie, zakres zwykle jest niszczony.
Prostym przykładem takiej funkcji jest:
W powyższym przykładzie funkcja buildName () deklaruje powitanie zmiennej lokalnej i zwraca ją. Każde wywołanie funkcji tworzy nowy zasięg z nową zmienną lokalną. Po zakończeniu wykonywania funkcji nie mamy możliwości ponownego odniesienia się do tego zakresu, więc są one usuwane.
Ale co powiesz, kiedy będziemy mieli link do tego zakresu?
Spójrzmy na następną funkcję:
Funkcja sayName () z tego przykładu jest zamknięciem. Funkcja sayName () ma własny zasięg lokalny (ze zmiennym powitaniem), a także ma dostęp do zasięgu funkcji zewnętrznej (zamykającej). W tym przypadku zmienne powitanie z buildName ().
Po zakończeniu wykonywania buildName zakres nie jest niszczony w tym przypadku. Funkcja sayMyName () nadal ma do niej dostęp, więc nie będzie usuwana. Jednak nie ma innego sposobu dostępu do danych z zakresu zewnętrznego poza zamknięciem. Zamknięcie służy jako brama między kontekstem globalnym a zasięgiem zewnętrznym.
źródło
Próbuję uczyć się klastrów i myślę, że przykład, który stworzyłem, jest praktycznym przykładem użycia. Możesz uruchomić fragment kodu i zobaczyć wynik w konsoli. mamy dwóch oddzielnych użytkowników, którzy mają osobne dane. Każdy z nich może zobaczyć aktualny stan i go zaktualizować.
źródło