Консоль — это не только console.log
console.log в JavaScript — первый инструмент отладки, который узнаёт каждый новичок, и последний, от которого многие так и не отказываются. Он работает, но у объекта console есть ещё с десяток методов, которые делают отладку быстрее и нагляднее. А когда освоитесь с самим DevTools — точками останова, стеком вызовов, watch-выражениями — к log будете обращаться заметно реже.
Для начала — небольшой обзор:
Все четыре метода пишут в одну и ту же консоль, но браузер оформляет их по-разному: предупреждения получают жёлтый фон, ошибки — красный и иконку, причём и те и другие сопровождаются стектрейсом. В DevTools есть фильтры, которыми можно скрыть или оставить только нужный уровень — штука полезная, когда приложение выдаёт сотни сообщений.
Как по-быстрому вывести сразу несколько значений
Если нужно глянуть несколько переменных разом, не склеивайте их в одну строку. Передайте их как отдельные аргументы — а ещё лучше оберните в объект, чтобы у каждого значения был свой ярлык:
Трюк { user, count } — это сокращённая запись объектов: имя переменной становится ключом. В консоли увидите { user: {...}, count: 3 }, а user можно раскрыть и изучить внутренности. При этом структура объекта не теряется — в отличие от варианта, где его приводят к строке.
console.table для массивов объектов в JavaScript
Когда перед вами массив объектов, console.log выдаёт свёрнутую кашу. А вот console.table отрисует всё в виде нормальной таблицы:
В консоли браузера первый вызов выведет все три строки с сортируемыми колонками. Второй — покажет только name и role. Для любых данных табличного вида — ответов API, результатов запросов, распарсенных CSV — это серьёзно упрощает жизнь.
console.dir vs console.log
На первый взгляд они похожи, но с DOM-элементами ведут себя по-разному:
const el = document.querySelector("button");
console.log(el); // выводит HTML: <button>Click me</button>
console.dir(el); // выводит представление JS-объекта со всеми свойствами
log показывает элементы как HTML, а вот dir раскрывает сам объект — все свойства, все обработчики событий, все ссылки на вычисленные стили. Когда нужно узнать, какие методы и атрибуты есть у элемента, выручает именно console.dir.
Группировка связанных сообщений в консоли
Во время долгой отладки консоль быстро превращается в свалку. console.group вместе с console.groupEnd собирают связанные сообщения в сворачиваемый блок:
Каждый вызов создаёт именованную группу, которую можно свернуть. Если хочется, чтобы группы по умолчанию были уже свёрнуты, используйте console.groupCollapsed — удобно, когда вы планируете раскрывать только те, что выглядят подозрительно.
Замер времени выполнения через console.time
Для быстрых замеров производительности сложно придумать что-то лучше связки console.time и console.timeEnd:
Метки в time и timeEnd должны совпадать. Можно запускать несколько таймеров одновременно — главное, чтобы у каждого была своя метка. Но если вопрос серьёзнее, чем «тормозит ли этот цикл?», переключайтесь на вкладку Performance в DevTools: там вы получите полный таймлайн и flame-график.
Ассерты: логируем, только когда что-то пошло не так
console.assert выводит сообщение только в том случае, если условие ложно. Это тихий способ оставить проверки-страховки в коде, не засоряя консоль, когда всё в порядке:
Хорошо подходит для инвариантов, которые обязаны выполняться всегда. Плохо — для ситуаций, где сбой вполне законен: в таких случаях лучше бросать ошибку.
Стек вызовов по запросу
console.trace выводит текущий стек вызовов, ничего при этом не выбрасывая. Удобно, когда нужно понять, кто вообще вызвал функцию:
Вывод идёт в порядке inner → outer → (top level). В реальном приложении именно так вы обнаруживаете, что обработчик клика, который вы отлаживаете, дёргается сразу из трёх разных мест.
Оператор debugger
Самый быстрый способ поставить JavaScript на паузу — одно-единственное слово:
function computeTotal(items) {
const subtotal = items.reduce((s, i) => s + i.price, 0);
debugger;
return subtotal * 1.08;
}
When DevTools is open, debugger; acts like a breakpoint — execution pauses on that line and you get the full debugger: variables in scope, the call stack, step-over and step-into controls, the ability to evaluate expressions against the current state. When DevTools is closed, debugger; does nothing.
Первый раз, когда вместо console.log вы пользуетесь настоящим отладчиком, это ощущается как суперспособность. Видно все переменные в текущей области, не нужно заранее решать, что именно вывести. Можно пошагово пройти по условиям и увидеть, какая ветка реально выполнилась. Поиск хитрого бага сокращается с минут до секунд.
Не забудьте убрать debugger перед коммитом. А ещё лучше — расставляйте точки останова прямо в DevTools, кликая по номеру строки на панели Sources.
Фишки Chrome DevTools, о которых стоит знать
Несколько возможностей, которые многие годами не замечают:
- Условные точки останова: кликните правой кнопкой по номеру строки в Sources и задайте условие, например
user.id === 42. Брейкпоинт сработает только когда условие истинно. - Logpoints: в том же меню — «Add logpoint». Выводит сообщение без паузы и без правок в коде.
$_в консоли: результат последнего вычисленного выражения. Что-то выполнили — и через$_снова достаёте результат.$0: текущий выбранный элемент на панели Elements.$0.textContentпокажет содержимое того, по чему вы кликнули.- Сохранить как глобальную переменную: правый клик по любому значению в консоли и «Store as global variable». Получите
temp1,temp2и так далее — ковыряйтесь на здоровье. - Network → Copy as fetch: превращает любой запрос в вызов
fetch(), который можно вставить в консоль и подправить.
Ни одна из этих штук не обязательна. Но каждая экономит время, когда входит в мышечную память.
Наводим порядок перед продакшеном
Забытые console.log безобидны в разработке и шумят в продакшене. Пара привычек, которые помогают:
- Включите правило линтера (
no-consoleв ESLint), которое ловит случайные логи, с исключениями дляwarnиerror. - Оборачивайте подробное логирование в проверку:
if (process.env.NODE_ENV !== "production") console.log(...). - Для трассировочного вывода используйте
console.debug— большинство сборщиков и систем сбора логов умеют его отфильтровывать. - Ещё лучше — заведите небольшой модуль-логгер (или возьмите библиотеку вроде
debug), чтобы включать и выключать категории логов, не трогая код.
Логирование не бесплатное. Каждый вызов сериализует аргументы и пишет в буфер. В горячем цикле забытый лог способен ощутимо замедлить код.
Дальше: регулярные выражения
Отлаживать код, работающий со строками, придётся много — а значит, и с регулярками, самой компактной и самой загадочной частью языка. Следующая глава начнётся со спокойного обзора регулярных выражений в JavaScript и методов, которые с ними работают.
Часто задаваемые вопросы
Чем console.log отличается от console.dir?
console.log выводит значение так, как браузер считает нужным — например, DOM-элемент показывается как HTML-разметка. А console.dir всегда показывает объект именно как JS-объект со всеми его свойствами. Если нужно посмотреть не разметку элемента, а его свойства — берите console.dir.
Как отлаживать JavaScript в Chrome DevTools без console.log?
Откройте вкладку Sources, найдите нужный файл и кликните по номеру строки — там поставится точка останова (breakpoint). Когда выполнение до неё дойдёт, код встанет на паузу, и вы сможете посмотреть значения переменных, пройтись по шагам и выполнить любое выражение прямо в консоли. Ещё вариант — воткнуть debugger; прямо в код, это тоже сработает как breakpoint.
Как замерить время выполнения JavaScript-кода?
Оберните нужный кусок в console.time('метка') и console.timeEnd('метка') с одинаковой меткой — в консоль выведется прошедшее время в миллисекундах. Если нужна более глубокая картина, открывайте вкладку Performance в DevTools: она запишет flame chart всего, что происходило во время выполнения.
Для чего нужен console.table?
console.table рисует массивы и объекты в виде нормальной таблицы с сортировкой — читать её гораздо удобнее, чем раскрывать вложенный объект. Особенно круто работает на массивах объектов: каждый объект превращается в строку, а его ключи становятся колонками. Вторым аргументом можно передать список колонок, которые хотите видеть.