2011-07-14 12 views
30

W pewnym momencie w przeszłości, czytałem coś który dał mi pomysł, że anonimowe funkcje w JavaScript może zużyć zaskakującą ilość pamięci (ponieważ prowadzą one cały zakres bieżącej wokół nich), natomiast nazwany (statyczny?) funkcje nie mają tego problemu.Czy są jakieś wady korzystania z anonimowych funkcji w JavaScript? Na przykład. użycie pamięci?

nie pamiętam gdzie czytałem to, więc nie mogę wrócić i ponownie ją przeczytać i dowiedzieć się tego na własne oczy.

Mam dwa pytania:

  1. Czy istnieją sytuacje, w których funkcje anonimowe można używać wystarczającej ilości pamięci, aby była ona warta dbając o? (Jeśli tak, czy masz przykład?)
  2. Czy istnieją inne wady anonimowych funkcji (w przeciwieństwie do nazwanych/statycznych funkcji)?
+0

Doskonałe pytanie. Wykorzystałem swoje głosy na ten dzień - czy ktoś inny może dla mnie dać +1? –

+0

@Michael Już zrobił. Świetne pytanie. –

+0

Było podobne pytanie na SO o * implementacji * zamknięć, ale jeszcze nie widziałem jednego z satysfakcjonującą odpowiedzią. To znaczy, czy * nowoczesne * silniki JavaScript są na tyle inteligentne, aby trzymać tylko obiekty w [[scope]], które * mogą * być dostępne? Oczywiście ta optymalizacja nie jest praktyczna do zastosowania w obecności 'eval', etc ... –

Odpowiedz

7

Wszystkie funkcje JavaScript będzie zachowywać się w taki sam sposób, w który oni dziedziczą zmienne środowiska w całym łańcuchu zasięgu prowadzących do i tym sami. Dotyczy to zarówno funkcji anonimowych, jak i nazwanych.

Łańcuch odniesień do środowiska zewnętrznego zostaje ze wszystkich funkcji, nawet wtedy, gdy funkcja jest przekazywana do zupełnie innego zakresu.

Tradycyjnie, oznaczałoby to, że wszystkie zmienne w danym łańcuchu mają odniesienie zatrzymany do nich tak długo, jak wewnętrzna zamknięcie nadal istnieje. Chociaż w nowoczesnych przeglądarkach, które kompilują kod, prawdopodobne jest, że nastąpi analiza, które zmienne są faktycznie przywoływane, a tylko te będą zachowane, pozwalając innym, które nie są już przywoływane, do zbierania śmieci.

Istnieją jednak inne sytuacje, w których funkcja anonimowa jest marnotrawstwem.

Oto wspólny kawałek kodu:

for(var i = 0; i < 100; i++) { 
    (function(j) { 
     setTimeout(function() { console.log(j); }, 1000); 
    })(i); 
} 

Jest to sytuacja, w której anonimowa funkcja jest nieco bardziej rozrzutny niż nazwie funkcji, ponieważ jesteś odtworzyć identyczną funkcję 100 razy podczas pętli, kiedy może po prostu ponownie użyć nazwanego.

function setConsole(j) { 
    setTimeout(function() { console.log(j); }, 1000); 
} 

for(var i = 0; i < 100; i++) { 
    setConsole(i); 
} 

Ma to dokładnie ten sam narzut zamknięcia, ale jest bardziej wydajny, ponieważ skonstruowano tylko jedną funkcję do tworzenia każdego nowego środowiska zmiennych.

http://jsperf.com/immediate-vs-named(Dzięki @Felix Kling dla jsPerf.)

Jeśli chodzi o zamknięcie, to tak, tak, tak długo, jak utrzymujesz zamknięcie przez stałe odniesienie. Powiedziałbym, że dobrze jest tego uniknąć, jeśli to możliwe, ale nie być obsesyjnym na ten temat. Czasami nowe zmienne środowisko dodane do łańcucha zasięgu jest po prostu najlepszym rozwiązaniem.


EDIT:Here's an article from Google. W szczególności zobacz Unikanie pułapek z zamknięciami. w celu uzyskania informacji o wpływie na wydajność rozszerzenia łańcucha zasięgu oraz o twierdzeniu, że funkcje anonimowe są "wolniejsze" niż funkcje nazwane.

+1

** Uwaga moderatora ** _Commenty pod tą odpowiedzią zostały usunięte, ponieważ zdegenerowały się na więcej hałasu niż sygnał. Zachowaj komentarze konstruktywne, profesjonalne i przede wszystkim na temat._ –

+1

Dzięki @Tim Post za usunięcie. Rezultat odpowiedniej dyskusji z OP, a także test wydajności dostarczony przez @Felix Kling został dodany do odpowiedzi. – user113716

3

Myślę, że prawdopodobnie czytałeś o problemie wycieku pamięci IE.

Spójrz na numer this article w tej sprawie.

Zasadniczo, w starszych wersjach IE, garbage collector nie może obsługiwać okrągłe referencji obejmujących obiekty DOM. Ponieważ zamknięcia są bardzo sprzyjające takim okrężnym odniesieniom, mogą łatwo doprowadzić do irytujących wycieków pamięci w IE.

+0

Tak, nie jestem pewien, czy to było - pamiętam IE okrągłe odniesienie rzecz , i że ma to związek z zamknięciami (nigdy nie byłem w stanie uzyskać pełnych informacji na ten temat), ale myślę, że * to, co przeczytałem, było bardziej ogólną kwestią dotyczącą anonimowych funkcji. –

0

To prawda, ze względu na zamknięte zamknięcia. z reguły największym problemem związanym z tą praktyką są obawy o wydajność z IE (szczególnie starszymi wersjami IE), który ma fatalne osiągnięcia w prawidłowym radzeniu sobie z nimi.

Powiązane problemy