Po prostu z ciekawości, czy zamknięcia w JavaScript uzyskują odniesienie do całego "środowiska zewnętrznego", czy też zwracana funkcja jest analizowana, aby zobaczyć, które zmienne w zewnętrznym zasięgu się odsyła, a następnie otrzymuje tylko odniesienia do nich?Czy zamknięcia w JavaScript mają odwołanie do pełnej funkcji zewnętrznej lub czy otrzymują tylko odniesienia do zmiennych, których faktycznie używają?
Odpowiedz
Teoretycznie funkcja zagnieżdżona w JavaScript ma dostęp do wszystkich zmiennych we wszystkich zawierających zakresy. Po napotkaniu identyfikatora jest on rozwiązywany względem łańcucha zasięgu , który jest listą zawierającą obiekty, których właściwościami są zmienne i parametry funkcji każdego kontekstu wykonawczego zawierającego (tj. Funkcję otaczającą), najbardziej wewnętrzną, plus obiekt globalny w koniec. Obiekt funkcyjny ciągnie za sobą łańcuch zasięgu, gdziekolwiek się znajduje.
Jednak te obiekty zmiennych i łańcuch zasięgu są tylko konstrukcjami specyfikacji i nie są dostępne bezpośrednio, więc implementacje mogą dowolnie wybierać optymalizacje, w tym analizować kod funkcji i ujawniać tylko zmienne, do których dostęp ma funkcja i dowolny funkcje zagnieżdżone w nim, o ile specyfikacja zawsze wydaje się być spełniona. Jednak najlepiej jest założyć, że jeśli masz ogromny obiekt, który jest dostępny poprzez zamknięcie funkcji, ten olbrzymi obiekt będzie się trzymał co najmniej do czasu, aż ta funkcja nie zostanie zebrana.
Jeśli chcesz uzyskać więcej informacji na ten temat, przeczytaj specyfikację ECMAScript. Dobrym punktem wyjścia będzie sekcja 10.1.4: http://bclary.com/2004/11/07/#a-10.1.4. Nie jest to aktualna wersja specyfikacji, ale stanowi punkt odniesienia dla wszystkich aktualnych głównych przeglądarek.
Odpowiedź brzmi "tak i nie". Gdy funkcja "wycieka" z aktywacji funkcji, cały kontekst zostaje zachowany *. Ponieważ jednak nie ma możliwości odwołania się do samego kontekstu, kod funkcji nie może "zbadać" kontekstu (ów). Tak więc:
function leaker() {
var i = 100, j = "hello there";
return function() {
i = i - 1;
return i == 0;
}
}
Zwrócona funkcja może odnosić się tylko do "i". Zmienna "j" może się trzymać, ale nie ma możliwości, aby kod w tej zwracanej funkcji "znalazł" ją.
* Piszę, że kontekst został zachowany, co uważam za prawdziwe, ale technicznie jest to sprawa tłumacza/środowiska wykonawczego.
Oznacza to, że w zasadzie otrzymuje się przecieki pamięci, jeśli zdefiniujesz jakiś duży obiekt w kontekście, ponieważ pozostanie on w pamięci przez cały czas trwania zamknięcia, nawet jeśli nie jest przez niego używany. – Sam
Cóż, nie jestem pewien, jak sprytni są śmieciarze; mogą mieć sposób radzenia sobie z tym, choć wydaje mi się to dość sci-fi. Jest to interesujące pytanie i naprawdę nie jestem ekspertem od JavaScriptu :-) – Pointy
@Pointy Myślę, że jest blog na temat zamknięcia powodującego wycieki pamięci, jeden używa obiektów typu instantiate, a drugi to zamknięcie. – kjy112
- 1. odwołanie do uniwersalnego odniesienia do priorytetu odniesienia?
- 2. Odwołanie do odniesienia w C++
- 3. Czy zwróciło się odwołanie do złych praktyk zmiennych zmiennych?
- 4. Czy powiązanie odniesienia faktycznie ocenia operand?
- 5. Debuger Visual Studio: czy po wejściu do funkcji zewnętrznej?
- 6. Python - Czy można przekazać self do funkcji zewnętrznej?
- 7. niezdefiniowane odwołanie do funkcji szablonu
- 8. Czy obiekty funkcji lub typy w JavaScript?
- 9. Wykrywanie, czy zmienną PHP jest odwołanie/odniesienie
- 10. Odwołanie do funkcji w zmiennej?
- 11. Jak uzyskać dostęp do zmiennych w innym zakresie wewnątrz funkcji przy użyciu zamknięcia w javascript?
- 12. Zadzwoń do zewnętrznej funkcji JavaScript z reakcji komponentów
- 13. Skrobanie zmiennych JavaScript do PHP
- 14. Zamknięcia JavaScript i nazwa clobbering
- 15. odwołanie do zmiennej javascript/alias
- 16. odniesienia zawaleniem dla zmiennych lokalnych
- 17. Jak dodać odwołanie do JavaScript lub css z szablonu edytora?
- 18. Rodzaj odniesienia bez pełnej nazw
- 19. Wyrażenie lambda lub odwołanie do metody?
- 20. Czy Google zaczyna korzystać z Dart? Czy oni zbudowali kompilator zamknięcia (lub GWT) do Dart?
- 21. Czy istnieje odwołanie do składni databinding SharePoint?
- 22. Czy musimy sprawdzić, czy faktycznie przydzielono obiekty?
- 23. Przekazywanie zmiennych ruby do funkcji javascript w widoku szyn
- 24. Czy to jest odwołanie do przekazywania?
- 25. Określanie, czy odwołanie do klasy C#
- 26. Czy można zdefiniować wskaźnik do odniesienia?
- 27. Javascript zamknięcia performance
- 28. Czy ten kod naprawdę powoduje problem "dostęp do zmodyfikowanego zamknięcia"?
- 29. Czy istnieje pełna lista zmiennych, których można użyć w formularzu_div_layout.html.twig?
- 30. Jak pomyślnie przekazać odwołanie do funkcji do funkcji reverse() Django?
Przypuszczam, że jedynym sposobem na przetestowanie tego byłoby stworzenie kontekstu, który ma kilka ogromnych zmiennych, stworzenie zamknięcia, które uzyskuje dostęp do innych zmiennych w kontekście, a następnie "wystarczające" alokacje i rezygnację, które rzuca śmieci i zobacz, czy pamięć dla ogromnych zmiennych jest uwolniona, czy nie. W przeciwnym razie jest to tylko kwestia akademicka specyficzna dla tłumacza, prawda? – Phrogz