2013-05-23 10 views
6

Chyba brakuje mi bardzo ważną rzeczą javascriptCo dzieje się z lokalnymi funkcjami, do których odwołuje się zdarzenie w JavaScript?

var gl = 10 
$(document).ready(function() { 
    var obj = {} 
    obj.test = function() { 
     gl++ 

     var lc = gl 
     function y() { 
      alert('local = ' + lc) 
     } 

     (function() { 
      var k = lc + 1 
      $('#button').click(function() { 
       alert('local anonymous = ' + k) 
       y() 
      })     
     })(); 

    } 

    obj.test() 
    $('#button').off() 
    obj.test()   
}) 

W scenariuszu powyżej mam zdefiniowany przedmiot „obj” i stworzył metodę „test” dla tego obiektu. Wewnątrz metody mam lokalną funkcję "y()", która jest używana przez zdarzenie "kliknięcie" dołączone do przycisku. Również zdarzenie click jest dołączane w funkcji anonimowej.

Następnie dzwonię "test()", anuluję subskrypcję zdarzenia "kliknięcie" z przycisku i ponownie wywołuję "test()". W rezultacie otrzymuję lokalny = 12 i lokalny anonimowy = 13, który jest oczekiwany.

Jednak nie rozumiem, co javascript ma w pamięci, szczególnie do funkcji "y()" i anonimowej funkcji w każdym z tych kroków.

Moje szczegółowe pytania znajdują się poniżej, ale byłbym bardzo wdzięczny, jeśli potrafisz wyjaśnić cały proces.

Po detekcji zdarzeń odnoszących się do pierwszego "obj.test()". W tym przypadku myślę, że to tylko wydarzenie typu "kliknięcie". Czy javascript zniszczy zakres obj.test() i wszystkie funkcje, w tym anonimowy zakres funkcji? Czy muszę dbać o coś innego?

Mój przypadek użycia: Tworzę dynamiczne ładowanie stron z różnymi zachowaniami strony, dlatego chciałem oddzielić javascript dla każdej strony w metodach obiektów globalnych i po załadowaniu nowej strony chciałem odłączyć wszystkie zdarzenia dla poprzednią stronę i wywołaj funkcję zachowania. Ale nagle uświadomiłem sobie, że tak naprawdę nie rozumiem, jak działa javascript i potencjalnie mogą być naprawdę olbrzymie wycieki pamięci w tym podejściu. : -)

Wielkie dzięki!

+2

Może to być pomocne w wyjaśnieniu, jak/dlaczego to działa: [Zamknięcia JavaScript] (http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) ... – War10ck

Odpowiedz

3

Podczas korzystania .off aby rozpiąć zdarzenia click, lc, k i y() są w tym momencie swobodnie być zbierane śmieci (GC) przez przeglądarkę, gdy GC ran. W następnej linii zadzwoniłeś pod numer obj.test(), więc obj w tym momencie nie będzie można pobrać ze śmieci, ponieważ uruchomiłeś go ponownie po rozłączeniu zdarzenia kliknięcia. lck i y() są teraz zdefiniowane ponownie w oddzielnym zakresie od pierwszego wywołania programu, oryginalne wersje nadal mogą być gc'd, ale nowe nie. Jeśli zdarzenie kliknięcia zostanie później niezwiązane, lc, k, y() i obj nie będzie już odwoływane przez nic, a zatem będzie wolne dla gc.

Powyższe jest nieco mylące, postaram się, aby było bardziej zrozumiałe.

Dopóki coś wewnątrz obj odniesień coś w zakresie, który jest powyżej zakresu utworzonego przez obj.test(), obj nie zostaną usunięte śmieci. Podczas gdy zdarzenie jest powiązane z powodu wywołania obj.test(), program obsługi zdarzeń odwołuje się do zmiennych wewnątrz zakresu obj.test(), a element jest częścią domeny, więc nie można pobrać śmieci, dopóki zdarzenie nie jest już powiązane z elementem.

Oto przykład:

(function(){ 
    var a = 1; 
    function doA() { 
     a++; 
    } 
    $("#myEl").click(doA); 
})(); 

Dopóki istnieje zdarzenie click na #myEl, a i doA śmieci nie mogą być gromadzone.

+0

Dzięki za Twoja odpowiedź. Teraz jest jasne! Co osobiście poleciłbyś do dynamicznego wczytywania strony: aby mieć jeden plik javascript i zarejestrować wszystkie zdarzenia z wyprzedzeniem dla wszystkich stron (powiedzmy 20 stron dla prostej gry mobilnej) lub zrezygnuj z subskrypcji wszystkich wydarzeń na poprzedniej stronie i zasubskrybuj bieżącą (nie wiesz, jak bezpieczne jest to w praktyce)? – potomok

+0

To zależy od tego, jakie są strony. Wygląda na to, że to, co robisz, może sprawić, że te same zdarzenia będą obsługiwać wszystkie strony –

Powiązane problemy