• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Domknięcia (ang. closures) - prawidłowe ich zrozumienie i przykłady wykorzystania w JS

Object Storage Arubacloud
+3 głosów
2,003 wizyt
pytanie zadane 10 lutego 2016 w JavaScript przez ScriptyChris Mędrzec (190,190 p.)
edycja 10 lutego 2016 przez ScriptyChris

Czytam o obecności domknięć (closure) w JavaScript i, o ile chyba rozumiem zasadę działania to, chciałbym znaleźć praktyczne zastosowania tych (rodzajów?) funkcji.

W skrócie (tak to rozumiem) - funkcja A stworzona wewnątrz innej (zewnętrznej) funkcji B, zapamiętuje jej całe ciało; co może być później wykorzystane do dalszych obliczeń.

Czyli np.:

var outer = function(outerVar)
{
    return function (innerVar)
    {
            console.log(outerVar + ' ' + innerVar);
    }
}

var resultOfBoth = outer(2);
resultOfBoth(3); // wynik = 5;

Jeśli nic nie pomieszałem to funkcja outer, w momencie jej wywołania, przechowa parametr jej przekazany - czyli 2 - zwracając funkcję inner, która będzie już ten parametr "mieć" (JS przechowa go w pamięci, ale już nie będzie "pamiętał" skąd ten parametr się tam wziął?). W momencie wywołania zmiennej(?) resultOfBoth, która przechowuje już (zwróconą) funkcję inner z parametrem 2 - przekazuje jej parametr 3. Ostatecznie funkcja inner posiada dwa parametry (2 i 3), które wyświetli w konsoli.

Teraz moja hipoteza: W domknięciu chodzi o to, aby wewnętrzna funkcja - pomimo zakończenia działania funkcji zewnętrznej - ZAPAMIĘTAŁA sobie zawartość jej ciała (czyli wszystkich zmiennych/funkcji/obiektów/parametrów, które były tam zadeklarowane w momencie jej wywołania).

Jeśli moje przypuszczenie jest prawidłowe, to czy dobrze wnioskuję, że domknięcie jest przydatne np. jeśli chcemy uzyskać wynik działania (czy też przetwarzania danych) jakiejś funkcji później? Bo jeśli domknięcie powoduje, że funkcja zadeklarowana wewnątrz (np. inner()) zapamiętuje jej całą zawartość, to gdy zostanie ona później wywołana - odtworzy przetworzone dane (funkcji outer()) nawet w innym miejscu kodu. Bo przecież nie trzeba wywoływać funkcji od razu, ale można sobie ją wywołać gdzie indziej, jeśli scope na to pozwoli lub przekaże się funkcję jako parametr.

Nie rozumiem natomiast przytoczonego przykładu w akapicie "Practical closures" z MDN:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Jest tam pokazana zmiana rozmiaru czcionki po kliknięciu w przycisk. Biorąc pod uwagę mój tok rozumowania i użyteczności domknięć, w jakim celu użyto closure w tym przykładzie?

function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + 'px';
  };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

Przecież wystarczy zwykła funkcja bez "zapamiętywania" ciała funkcji zewnętrznej. Czy w tym przykładzie chodzi o co innego?

P.S. Wiem, że w dalszej części tutoriala z MDN jest więcej przykładów dla zastosowania closures, ale są one bardziej zaawansowane i stwierdziłem, że chcę najpierw zrozumieć prostsze przykłady.

3 odpowiedzi

+3 głosów
odpowiedź 10 lutego 2016 przez Comandeer Guru (601,450 p.)

W przykładzie z MDN do zmiennych zapisywane są funkcje, które pozwalają na zmianę rozmiaru czcionki:

size12(); // czcionka zmieniona na 12px
size14(); // czcionka zmieniona na 14px

Generalnie można powiedzieć, że każda funkcja tworzy własny scope (własny execution context – kontekst wykonania), dlatego wszystko, co jest zamknięte w jakąś funkcję, ma dostęp do jej zmiennych. Z tej samej przyczyny closures pamiętają wszystko, co zostało przekazane do ich rodzica.

komentarz 10 lutego 2016 przez ScriptyChris Mędrzec (190,190 p.)

Ale w przykładzie z MDN domknięcie jest raczej zbędne. Prościej, moim zdaniem, zrobić to tak: (pełne DEMO https://jsfiddle.net/mrdp6pke/)

document.addEventListener('click', function(ev)
{
    document.body.style.fontSize = ev.target.innerHTML + 'px';
}, false);

Dlatego nie rozumiem, po co tam jest closure użyte i chciałbym wiedzieć, czy moje przypuszczenia co do użyteczności domknięć są dobre :)

Czyli czy można sobie "zachować" wynik działania jakiejś funkcji, a potem za pomocą zwróconej funkcji wykonywać coś dalej.

komentarz 10 lutego 2016 przez Comandeer Guru (601,450 p.)
No ok, średnio przydatny przykład ;)

Co do tego, o czym mówisz: to tzw. currying → http://engineering.cerner.com/blog/closures-and-currying-in-javascript/
+1 głos
odpowiedź 27 lutego 2016 przez piotrusg19 Początkujący (280 p.)
edycja 27 lutego 2016 przez piotrusg19
Przy domknięciach chodzi głównie o to żeby wymusić kolejność wykonywania czynności w kodzie. Np. W linii 120 wykonuje się jakąś skomplikowana funkcja (zajmująca stosunkowo dużo czasu) a w linii 121 wyświetlany jest wynik działania funkcji z linii 120. Przy działaniu asynchronicznym (np. w nodejs, angular itp) może zdarzyć się tak że funkcja z linii 121 wykona się wcześniej niż ta z 120. Domykanie ma zapobiec takim sytuacjom. Jak usiądę przy komputerze i nie zapomnę podam kilka spektakularnych przykładów (teraz korzystam z komórki). Poniżej modelowe przykłady domknięć:

http://dreamerslab.com/blog/en/javascript-callbacks/
0 głosów
odpowiedź 10 stycznia 2019 przez daniel1806 Obywatel (1,780 p.)
Dorzucę swoje 3 grosze :)

Jak sobie porównasz obiekty w JavaScript i w np. C++ to pierwsze co się w oczy rzuca to brak enkapsulacji w js. W każdej chwili jakikolwiek programista w zespole może zmienić właściwości dowolnego obiektu nawet nie grzebiąc w jego kodzie. W językach z dziedziczeniem opartym na klasach jak np.: C++ mamy klauzule dostępu tj.: "public", "private", "protected", których nie ma w js. Z tego co wyczytałem o domknięciach, to mogą one jedynie emulować (ale to zawsze coś :)) enkapsulację. Do zmiennych zapamiętanych w leksykalnym środowisku podczas tworzenia funkcji ma dostęp tylko ta funkcja. Nie ma opcji, żeby ktoś popsuł wewnętrzne dane. Domknięcie zachowuje się jak obiekt a jego funkcja zachowuje się jak publiczna metoda operująca na prywatnych atrybutach.

Pewnie jest masa innych zastosowań, ale ta cecha domknięć mi osobiście najbardziej się rzuca w oczy.

Podobne pytania

+1 głos
0 odpowiedzi 162 wizyt
0 głosów
2 odpowiedzi 1,108 wizyt
pytanie zadane 20 lutego 2016 w Mikrokontrolery przez programer Obywatel (1,190 p.)
0 głosów
3 odpowiedzi 440 wizyt

92,575 zapytań

141,425 odpowiedzi

319,650 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...