Ответ 1
console.log
не стандартизирован, поэтому поведение довольно неопределенное и может быть легко изменено от выпуска к выпуску инструментов разработчика. Ваша книга, скорее всего, устарела, как и мой ответ в ближайшее время.
Для нашего кода не имеет значения, является ли console.log
асинхронным или нет, он не обеспечивает какого-либо обратного вызова или около того; и на значения, которые вы передаете, всегда ссылаются и вычисляют во время вызова функции.
Мы действительно не знаем, что произойдет тогда (хорошо, мы могли бы, так как Firebug, Chrome Devtools и Opera Dragonfly все с открытым исходным кодом). Консоль должна будет где-то хранить записанные значения и отображать их на экране. Рендеринг будет происходить точно асинхронно (будучи ограниченным обновлениями с ограничением скорости), как и будущие взаимодействия с зарегистрированными объектами в консоли (например, расширение свойств объекта).
Таким образом, консоль может либо клонировать (сериализовать) изменяемые объекты, которые вы записали в журнал, либо хранить ссылки на них. Первый не очень хорошо работает с глубокими/большими объектами. Кроме того, по крайней мере начальный рендеринг в консоли, вероятно, покажет "текущее" состояние объекта, то есть то, когда он был зарегистрирован - в вашем примере вы видите Object {}
.
Однако когда вы расширяете объект для дальнейшей проверки его свойств, вполне вероятно, что консоль будет хранить только ссылку на ваш объект и его свойства, и теперь при их отображении будет отображаться их текущее (уже измененное) состояние. Если вы нажмете на +
, вы сможете увидеть свойство bar
в вашем примере.
Вот скриншот, который был опубликован в отчете об ошибке, чтобы объяснить их "исправление":
Таким образом, на некоторые значения можно ссылаться задолго до их регистрации, и их оценка довольно ленива ("при необходимости"). Наиболее известный пример такого несоответствия рассматривается в вопросе : ленива ли консоль JavaScript в Chrome при оценке массивов?
Обходной путь должен всегда регистрировать сериализованные снимки ваших объектов, например, с помощью console.log(JSON.stringify(obj))
. Это будет работать только для некруглых и довольно маленьких объектов. Смотрите также Как я могу изменить поведение по умолчанию console.log в Safari? ,
Лучшее решение - использовать точки останова для отладки, когда выполнение полностью останавливается, и вы можете проверить текущие значения в каждой точке. Используйте ведение журнала только с сериализуемыми и неизменными данными.