Zacznę od kodu:
var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
Proste, prawda? W odpowiedzi na to Firebug mówi:
["hi"]
["bye"]
Cudownie, ale konsola JavaScript Chrome (7.0.517.41 beta) mówi:
["bye"]
["bye"]
Czy zrobiłem coś nie tak, czy też konsola JavaScript Chrome jest wyjątkowo leniwa w ocenie mojej tablicy?
javascript
arrays
logging
google-chrome
console
Eric Mickelsen
źródło
źródło
i
w podpowiedzi z niebieską ikoną jest napisane „Poniższa wartość została właśnie oszacowana”.Odpowiedzi:
Dzięki za komentarz, tec. Udało mi się znaleźć istniejący niepotwierdzony błąd Webkita, który wyjaśnia ten problem: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDYCJA: teraz naprawiona!)
Wydaje się, że trwa dyskusja na temat tego, jak bardzo jest to błąd i czy można go naprawić. Wydaje mi się, że to złe zachowanie. Było to dla mnie szczególnie niepokojące, ponieważ przynajmniej w Chrome występuje, gdy kod znajduje się w skryptach, które są wykonywane natychmiast (przed załadowaniem strony), nawet gdy konsola jest otwarta, za każdym razem, gdy strona jest odświeżana. Wywołanie polecenia console.log, gdy konsola nie jest jeszcze aktywna, powoduje jedynie odniesienie do obiektu znajdującego się w kolejce, a nie wyjście, które będzie zawierać konsola. Dlatego tablica (lub dowolny obiekt) nie będzie oceniana, dopóki konsola nie będzie gotowa. To naprawdę jest przypadek leniwej oceny.
Istnieje jednak prosty sposób, aby tego uniknąć w kodzie:
Wywołując toString, tworzysz reprezentację w pamięci, która nie zostanie zmieniona przez następujące instrukcje, które konsola odczyta, gdy będzie gotowa. Wynik konsoli różni się nieco od bezpośredniego przekazywania obiektu, ale wydaje się akceptowalny:
źródło
Z wyjaśnień Erica wynika, że jest
console.log()
to kolejka do kolejki i drukuje późniejszą wartość tablicy (lub obiektu).Może być 5 rozwiązań:
źródło
Możesz sklonować tablicę za pomocą
Array#slice
:Funkcja, której możesz użyć zamiast niej
console.log
, nie ma tego problemu, jest następująca:W przypadku obiektów, niestety, najlepszą metodą wydaje się być debugowanie najpierw za pomocą przeglądarki innej niż WebKit lub napisanie skomplikowanej funkcji do sklonowania. Jeśli pracujesz tylko z prostymi obiektami, w których kolejność klawiszy nie ma znaczenia i nie ma żadnych funkcji, zawsze możesz zrobić:
Wszystkie te metody są oczywiście bardzo wolne, więc nawet bardziej niż w przypadku zwykłych metod
console.log
, musisz je usunąć po zakończeniu debugowania.źródło
Zostało to załatane w Webkit, jednak podczas korzystania z frameworka React zdarza się to w niektórych okolicznościach, jeśli masz takie problemy, po prostu użyj, jak sugerują inni:
źródło
JSON.parse(JSON.stringify(event))
nie ma odpowiedniej głębokości / dokładności. Oświadczenia debuggera to jedyne prawdziwe rozwiązanie, które znalazłem, aby uzyskać właściwy wgląd.To już odpowiedź, ale i tak odrzucę odpowiedź. Zaimplementowałem prosty wrapper konsoli, który nie cierpi z powodu tego problemu. Wymaga jQuery.
Implementuje tylko
log
,warn
aerror
metody, trzeba będzie dodać trochę więcej, aby mogła ona być stosowane zamiennie z regularnymconsole
.źródło
Wygląda na to, że Chrome zastępuje w fazie „prekompilacji” dowolne wystąpienie litery „s” wskaźnikiem do rzeczywistej tablicy.
Jednym ze sposobów jest sklonowanie tablicy i zarejestrowanie nowej kopii:
źródło
jak dotąd najkrótszym rozwiązaniem jest użycie tablicy lub składni rozproszenia obiektów w celu uzyskania klonu wartości, które mają być zachowane w czasie logowania, tj .:
należy jednak uważać, ponieważ robi to płytką kopię, więc wszelkie głęboko zagnieżdżone wartości niebędące prymitywami nie zostaną sklonowane i tym samym wyświetlone w zmodyfikowanym stanie w konsoli
źródło