Используем console на полную

Материал из support.qbpro.ru

Метод console.log() — отличный способ вывести отладочную информацию, не мешая пользователю. Но знаете ли Вы, что объект console имеет еще уйму других не менее полезных методов? Очень редко разработчики используют этот функционал, ограничиваясь неблокирующим alert'ом. Что-ж, давайте исправим это положение.


Небольшое примечание: использование отладочного кода может негативно сказаться на производительности. Удаляйте его из продакшн версии.


Больше, чем просто сообщения

Перед тем, как погрузиться в малоизвестные методы console, рассмотрим функционал console.log подробнее. Например, возможность передачи любого числа аргументов:

var foo = {baz: "tubular", goo: "rad"}, bar = "baz";
console.log("string",1,foo.goo,bar,foo.baz); // string 1 rad baz tubular


В результате все переданные аргументы будут выведены и разделены пробелом. Это, конечно, хорошо, но было бы еще лучше, если бы мы могли как-нибудь вывести все эти аргументы в виде красиво отформатированного сообщения. Хотя, постойте… мы можем!

Если Вы знакомы с функцией printf() в других языках, то спешим обрадовать: console.log() умеет вести себя похожим образом. Возьмем последний пример и передадим первый аргумент в немного измененном виде.

var foo = {baz: "tubular", goo: "rad"}, bar = "baz";
console.log(
    "%s theory is %d %s concept. I can only describe it as %s and %s",
     "string", 1, foo.goo, bar, foo.baz 
);
// string theory is 1 rad concept. I can only describe it as baz and tubular


Что за %s?

Отличный вопрос! Это управляющие последовательности, которые заменяются на соответствующие им значения (в порядке очередности). %s означает «трактовать значение как строку», %d — как число (Также можно использовать %i или %f).

Каждое вхождение такой последовательности будет заменено на следующий по порядку аргумент. Первое вхождение — на первый (за первым аргументом-строкой, конечно), ну и так далее.

Порядок использования аргументов можно изменить вручную, использовав символ $ и приписав перед ним номер аргумента, который мы хотим вывести:

var foo = {baz: "tubular", goo: "rad"}, bar = "baz";
console.log(
    "%2$d theory is %d %s concept. I can only describe it as %s and %s",
    "string",1,foo.goo,bar,foo.baz
);
// 1 theory is 0 baz concept. I can only describe it as tubular and %s string


Эта команда как бы говорит «Я начну со второго аргумента и продолжу, начиная со следующего». Как Вы видите, последовательности, которым не хватило аргументов, остались нетронутыми.

Первый аргумент (строка формата) также участвует в нумерации (она идет с нуля) аргументов. Таким образом, в нашем примере последний аргумент будет иметь номер 5. Но мы задали всего 5 аргументов и, при этом, начали со второго. Поэтому, последней управляющей последовательности аргументов не досталось, и она не изменилась.

Чтобы это исправить, можно изменить формат строки таким образом, чтобы «указатель» не следующий элемент синхронизировался со списком аргументов в определенный момент. Тогда все будет работать как положено.

var foo = {baz: "tubular", goo: "rad"}, bar = "baz";
console.log(
    "%2$d theory is %1$s %3$s concept. I can only describe it as %s and %s",
    "string",1,foo.goo,bar,foo.baz
);
// 1 theory is string rad concept. I can only describe it as baz and tubular


Для того, чтобы аргументы были выведены правильно, нам нужно изменить порядок вывода второго и третьего элементов. Другие элементы и так в правильном положении, так что нет необходимости указывать их позиции. Аргументы будут использованы в следующем порядке: 2, 1, 3, 4, 5.

Форматирование строк — мощный инструмент, и я охватил только вершину айсберга. Попробуйте поиграться самостоятельно и почитать, что пишет Joe Hewitts о консоли.

Различные типы сообщения

Есть еще пара методов, подобных log, но отличающихся внешне. А именно: console.info(), console.warn() и console.error().

console.info("%s numbers %d, %d and %d","hello",1,2,3); // hello numbers 1, 2 and 3
console.warn("%s numbers %d, %d and %d","hello",1,2,3);
console.error("%s numbers %d, %d and %d","hello",1,2,3);
console.info(), console.warn() и console.error() в Firebug'е.

Все три метода умеют выводить строки в соответствие с форматом и принимать любое количество аргументов.

Логи DOM'а

Когда Вам нужно как-то указать в логах на DOM узел лучшего всего использовать методы console.dir() или console.dirxml(), которые могут перечислить свойства элемента или вывести HTML кода элемента.

console.dir(document.documentElement);
console.dirxml(document.documentElement);
.

Группировка

Иногда бывает полезно сгруппировать логи для упрощения работы с ними. Для этого существуют методы console.group(), console.groupCollapsed() и console.groupEnd().

console.group("Overlord");
  console.log("Overlord stuff");
 console.group("Lord");
  console.log("Overlord stuff");
 console.group("Minion");
 console.log("Minion stuff");
console.groupEnd();
console.groupCollapsed("Servant");
 console.log("Servant stuff");
Группировка в консоли Safari.


Как Вы можете видеть, подряд идущие вызовы group создают вложенные папки. Чтобы закрывать папку, используйте метод console.groupEnd(). Метод console.groupCollapsed() аналогичен console.group() за тем лишь исключением, что группа со всем содержимым будет изначально свернута.

Профилирование и замеры

Также консоль позволяет точно замерять время, используя метод console.time() и console.timeEnd(). Расположите вызов первого из них перед кодом, время исполнения которого хотите замерить, а второго — после.

console.time("Execution time took");
// Some code to execute
console.timeEnd("Execution time took");
Пример работы console.time() и console.timeEnd() в Firefox


Таймеры связаны между собой метками (передаются первым аргументом и могут быть любой строкой), так что Вы можете запустить несколько таймеров одновременно. Когда сработает console.timeEnd(), будет выведено сообщение с меткой и прошедшим временем в миллисекундах.

Помимо замера времени можно профилировать Ваш код и вывести стек профилирования, который подробно показывает, где и сколько времени потратил браузер.

console.profile();
// Some code to execute
console.profileEnd();
Профилирование в Chrome.

Assert'ы

Когда Вы работаете над сложным проектом, важно покрывать код юнит тестами. Это позволит избежать глупых ошибок и возможных регрессий. К счастью, консоль включает в себя assert'ы.

Assert'ы позволяют обеспечивать соблюдение правил в коде и быть уверенным, что результаты выполнения этого кода соответствуют ожиданиям. Метод console.assert() позволяет проводить элементарное тестирование кода: если что-то пойдет не так, будет выброшено исключение. Первым аргументом может быть все, что угодно: функция, проверка на равенство или проверка существования объекта.

var a = 1, b = "1";
console.assert(a === b, "A doesn't equal B");
Assert в Chrome

Метод assert принимает условие, которое является обязательным к выполнению (в данном случае простая строгая проверка на равенство) и, вторым аргументом, сообщение, которое будет выведено в консоль вместе с выброшенным исключением, если первое условие не будет выполнено.

Поддержка браузерами

Большинство перечисленных методов поддерживаются достаточно хорошо. IE8+, Firefox с расширением firebug, Opera или webkit-браузер вроде Safari или Chrome. Есть, правда, некоторые различия: Firefox, Safari и Chrome отличаются более широкой поддержкой. Проще всего проверить совместимость можно выполнив console.dir(console), результатом которого будет вывод объекта console со всеми его методами.

Opera с Dragonfly поддерживает большинство методов, за исключением форматирования строк и профилирования (хотя методы profile, profileEnd и реализованы, это всего лишь заглушки).

IE8 также поддерживает много вкусностей, включая форматирование строк и assert'ы, но не замеры времени, профилирование, методы dir или dirxml.

Стоит отметить, что firebug lite может добавить некоторые методы к console в браузерах, их не поддерживающих.

Это не полный список того, что есть в console, но я перечислил наиболее полезные возможности, существенно упрощающие процесс отладки и тестирования. Используйте приобретенные знания и не ограничивайтесь одним лишь логированием строк.


Extra

Итак, это был очень вольный перевод статьи, но теперь я бы хотел добавить немного от себя: Node.JS (ветка 0.2) поддерживает методы log, info, warn, error, dir, time / timeEnd, assert и trace. log не умеет изменять порядок аргументов для подстановок, но сами подстановки реализованы. При вызове метода trace в консоль будет выведен стек вызовов (все методы ничего не возвращают, а просто пишут в консоль). Работает это также как минимум в Chrome и Opera.

В Opera и Chrome, помимо уже перечисленных, реализованы следующие методы: count — выводит, сколько раз уже выполнялась строка, на которой расположен вызов метода. Аргументом передается строка, которая будет выведена перед количеством вызовов. debug — ничем не отличается от log.

В Опере также есть метод table, который должен строить красивую табличку из аргументов, но ничего не делает. Вообще, Опера немного странновата. Результаты работы обсуждаемых функций нужно искать не в стандартной консоли, а на просторах Dragonfly (впрочем, это логично). Причем часть из них можно найти сразу в двух местах: на вкладке «Консоль ошибок» и «Скрипты» -> REPL.

Также в Chrome у объекта console есть свойство memory, являющееся объектом со свойствами totalJSHeapSize и usedJSHeapSize. Однако, в Chromium'е мне так и не удалось застать эти свойства со значениями, отличными от нуля.