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

Javascript nie rozumiem fragmentu kodu

0 głosów
436 wizyt
pytanie zadane 31 maja 2016 w JavaScript przez mac-rum Użytkownik (610 p.)

Witam, ostatnio gdzieś na forum w którymś z tematów Comaander polecil ksiazke nt. JavaScriptu, uznałem że wezmę się za lekturę. Stwierdziłem, że będe uczył się powoli, ale ze zrozumieniem, utknąłem jednak w pewnym miejscu. Może ktoś wytłumaczyłby mi jakoś 'łopatologiczniej' tą kwestię?

 

IIFE use case: inadvertent sharing via closures

Closures keep their connections to outer variables, which is sometimes not what you want:

var result = [];
for (var i=0; i < 5; i++) {
    result.push(function () { return i });  // (1)
}
console.log(result[1]()); // 5 (not 1)
console.log(result[3]()); // 5 (not 3)

The value returned in line (1) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value. If you want the function in line (1) to receive a snapshot of the current value of i, you can use an IIFE:

for (var i=0; i < 5; i++) {
    (function () {
        var i2 = i; // copy current i
        result.push(function () { return i2 });
    }());
}

Dlaczego 1 fragment zwraca 5?? Rozumiem, że w pewnym momencie i = 5, więc pętla zwraca false i nie idzie dalej, ale czemu funkcja zwraca tą właśnie 5 i to za każdym razem? Co niby zmienią tutaj funkcja samowywołująca w drugim fragmencie? Niby jest wyjaśnienie, ale dalej nie czuję tego. Nie mam tego "ahaaa, o to chodzi!". Siedze, patrzę w to.. No i nie mogę sobie jakoś wyjaśnić. Może coś źle tłumaczę na nasz język. Ktoś coś? z góry dzięki. Pozdrawiam.

2 odpowiedzi

+2 głosów
odpowiedź 31 maja 2016 przez Comandeer Guru (608,860 p.)

var tworzy zmienne o zasięgu funkcyjnym, zatem zamknięcie tej zmiennej w bloku, w jakim jest pętla, nic nie zmienia. Zmienna i po pętli jest tę samą, na której operowaliśmy w pętli – a zatem tą zmienną, która "przeżyła" 5 iteracji, ostatecznie przyjmując wartość 5.

Z tego wynika sens drugiego kodu: skoro zmienne deklarowane przez var mają zasięg funkcyjny, trzeba… zamknąć je wewnątrz funkcji ;) Tym samym nie mają się jak wydostać.

komentarz 1 czerwca 2016 przez mac-rum Użytkownik (610 p.)
ok, dziękuję za wyjaśnienie :) Myślę, że teraz "mam to". Swoją drogą fragmenty z książki:

Speaking JavaScript, An In-Depth Guide for Programmers - O' Reilly, mam nadzieję, że wciąż uważasz to za dobre źródło wiedzy, rekomendowałeś komuś na forum z rok temu :P

pozdrawiam.
+1 głos
odpowiedź 31 maja 2016 przez ScriptyChris Mędrzec (190,170 p.)

The value returned in line (1) is always the current value of i, not the value it had when the function was created. After the loop is finished, i has the value 5, which is why all functions in the array return that value.

Gdy wywołujesz funkcję poza pętlą, to closure umożliwia Ci dostęp do zmiennej (bo pamięta środowisko, w którym została utworzona zmienna), ale jej wartość jako ostatnia została ustawiona na 5 - bo na tym pętla się zakończyła.

IIFE powoduje, że funkcja wywołuje się w momencie jej tworzenia. W drugim przykładzie masz 

var i2 = i; // copy current i

Co powoduje, że wartość iteratora jest kopiowana (bo wartości prymitywne w JS, w przeciwieństwie do obiektów, są kopiowane) do tymczasowej zmiennej w momencie, gdy ma ona konkretną wartość- a dzięki IIFE, można potem ją wywołać z jej ówczesną wartością (taką, jaką wtedy miało i).

Tu masz więcej przykładów z IIFE: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

komentarz 1 czerwca 2016 przez mac-rum Użytkownik (610 p.)
Ok, dziękuję za dopełnienie wypowiedzi Comandeera :) Wydaje się, że kumam już zasadę działania. Zabieram się za artykuł z linku :) Pozdrawiam

Podobne pytania

0 głosów
1 odpowiedź 698 wizyt
pytanie zadane 2 listopada 2016 w Assembler przez Patryk Rafał Bywalec (2,700 p.)
0 głosów
1 odpowiedź 343 wizyt
0 głosów
2 odpowiedzi 1,749 wizyt
pytanie zadane 2 listopada 2017 w JavaScript przez Motorox122 Nowicjusz (170 p.)

93,757 zapytań

142,716 odpowiedzi

323,363 komentarzy

63,353 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

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...