вторник, 29 декабря 2009 г.

Используем FireBug для удобной отладки JavaScript

FireBug один из прекраснейших плагинов разработанных для FireFox. Он сочетает в себе удобство, широкий функционал и возможность написания своих дополнений. Вот уже долгое время FireBug стал для меня незаменимым помощником в веб программировании. Чего стоит возможность просмотра и редактирования html разметки, CSS стилей, мониторинг сетевых запросов и т.д. Каждый из инструментов, предоставляемый FireBug, отличается простой.

В данной статье хотел рассказать про то, как может помочь FireBug при отладке JavaScript кода, а именно про функции и возможности объекта console.

Логирования


Одной из самых незаменимых возможностей при разработке JavaScript сценариев является логирование. Используя FireBug вы получаете 3 преимущества:
1. Возможность задавать разные типы сообщений при логировании.
3. Можете воспользоваться строкой форматирования вывода.
4. Можете группировать сообщения логирования.

При логировании иногда важно разделять сообщения по типам критичности, что бы однозначно определить сбой ли это, небольшое отклонение, или просто сообщение про выполнения каких либо действий. FireBug поддерживает 5 типов логирования:
1. log - обычное сообщение.
3. debug - отладочное сообщение. В консоль возле такой записи будет добавлена ссылка на строку вызова.
2. info - информационное сообщение. Будет отображаться иконка информации (), а в тексте будет ссылка на строку вызова.
4. warn - сообщение предупреждение. Будет отображаться иконка предупреждения (), строка сообщение будет подсвечена цветом, а в тексте будет ссылка на строку вызова.
5. error - сообщения об ошибки. Текст такого сообщения будет красного цвета, будет отображаться иконка ошибки () и так же как у всех важных сообщений будет ссылка на строку вызова.

Методы имеют следующий формат:

console.log(object[, object, ...]); //обычное сообщений
console.debug(object[, object, ...]); //отладочное сообщение
console.info(object[, object, ...]); //информационное сообщение
console.warn(object[, object, ...]); //сообщение предупреждение
console.error(object[, object, ...]); //сообщения об ошибки


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

%s - сторока
%d, %i - целое число
%f - дробное число
%o - ссылка на объект

Если вы не задали в строке форматирования вывод какого то из параметров, то не беспокойтесь, данный параметр будет добавлен в конце строки. При выводе параметра типа объекта (%o) кроме текстового значение будет отображаться еще и ссылка, при клике на которую объект отобразится в табе DOM.

При выводе данный функционал будет выглядеть следующим образом

console.log("Тип сообщения: %s. Обычное сообщение", "log");
console.debug("Тип сообщения: %s. Отладочное сообщение", "debug");
console.info("Тип сообщения: %s. Информационное сообщение", "info");
console.warn("Тип сообщения: %s. Сообщение предупреждение", "warn");
console.error("Тип сообщения: %s. Сообщения об ошибки", "error");




Одной из интересных особенностей, которые обладает FireBug при логировании является группирование логов. Для этого присутствуют 3 функции: console.group, console.groupCollapsed, console.groupEnd.

Каждая из них имеет следующий формат

console.group(object[, object, ...]); //начало групирования
console.groupCollapsed(object[, object, ...]); //начало группирования, с сворачиванием результата
console.groupEnd(); //окончание групирования

Начало группы определяется функциями console.group и console.groupCollapsed, для того чтобы закрыть группу, необходимо вызвать функцию console.groupEnd. Так же можно добавлять подгруппы, количество подгрупп ограничено, наверное, только здравым смыслом :).

Например, у нас есть вот такой JavaScript. В котором желательно знать в каком из циклов возникли ошибки.

for(i = 0; i < 3; i++) {
if (i===0) {
console.groupCollapsed("Обработка вложенного цикла %s раз/а", i);
} else {
console.group("Обработка вложенного цикла %s раз/а", i);
}
for(j = i-2; j < i+2; j++) {
if (i-j>0){
console.error("ошибка в коде! i = %i; j = %i", i, j); //сообщения об ошибки
} else {
console.log("i = %i; j = %i", i, j);
}
}
console.groupEnd();
}

Вывод сообщений будет иметь следующий вид


Одна из интересных функций для отображения количество вызовов методов console.count.

for(i = 0; i < 3; i++) {
for(j = i-2; j < i+2; j++) {
console.count("Count set j = ");
}
}

Результат исполнения


Отслеживаем время выполнения


Для определения узких мест при разработке сценариев на JavaScript иногда приходиться отслеживать время выполнения. Для таких целей FireBug имеет два метода console.time, console.timeEnd и console.profile, console.profileEnd.

Если вам необходимо определить время выполнение части когда, пользуйтесь функциями console.time, console.timeEnd. При этом можете инициализировать множество таймеров. Рассмотрим работу на примере.

console.time("Весь цикл");
for(i = 0; i < 3; i++) {
console.time("Одна итерация");
if (i===0) {
console.groupCollapsed("Обработка вложенного цикла %s раз/а", i);
} else {
console.group("Обработка вложенного цикла %s раз/а", i);
}
for(j = i-2; j < i+2; j++) {
if (i-j>0){
console.error("ошибка в коде! i = %i; j = %i", i, j); //сообщения об ошибки
} else {
console.log("i = %i; j = %i", i, j);
}
}
console.groupEnd();
console.timeEnd("Одна итерация");
}
console.timeEnd("Весь цикл");

Результат логирования


Если же вы хотите определить время выполнения функции, количество вызовов каждой функции, процентное распределение между временем каждой функции, то вам лучше воспользоваться console.profile, console.profileEnd.

Для того чтобы начать отслеживание вызовете функцию console.profile, для окончания отслеживания, вам будет необходимо вызвать функцию console.profileEnd.

function first(){
for(i = 0; i < 3; i++) {
second(i);
}
}

function second(i) {
for(j = i-2; j < i+2; j++) {
var p = i*2-j%2+i*j;
}
}

console.profile("first");
first();
console.profileEnd();




Тестирование


Для построение тестовых сценариев можно воспользоваться функцией console.assert. Если выражение, которое будет передано в функцию ложь, то возникнет ошибка.


function first(){
for(i = 0; i < 3; i++) {
second(i);
}
}

function second(i) {
for(j = i-2; j < i+2; j++) {
var p = i*2-j%2+i*j;
console.log("Значение p=%i.",p);
console.assert(p>=0);
}
}

first();


Результат


Просмотр значение элементов


Тяжелый арсенал FireBug завершает функции console.dir и console.dirxml.

console.dir необходим для вывода в лог всех свойств или методов доступных у объекта.

function first() {
for(i = 0; i < 2; i++) {
for(j = i-1; j < i+1; j++) {
var p = i*2-j%2+i*j;
var m = ({ "item" : p, "item1" : p*100 });
console.dir(m);
}
}
}
first();

Результат выполнения


console.dirxml необходим для отображения xml дерева html элемента.

<table id="test">
<tr>
<td>пример 1</td>
<td>пример 2</td>
</tr>
</table>
<script type="text/javascript">
var t = document.getElementById('test');
console.dirxml(t);
</script>

Рузультат выполнения


Использования FireBug в разных браузерах


FireBug поставляется как плагин к FireFox. Если вы в сценарий внедряете такие функции, то при проверке в IE, Opera (Safari поддерживает такие же методы логирования) у вас возникнет исключение. Ситуацию можно исправить 2-мя способами.

Если вам не нужна проверка в остальных браузерах, то можете воспользоватся решением от Eric Nguyen, добавите на свою страницу следующий код.



if (!("console" in window) || !("firebug" in console))
{
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {}
}


Если же вам все же необходимы данные функции, то можете подключить FireBug Lite, который может работать в других браузерах. Для этого добавить следующий код себе на страницу.


window.onload = function() {
if (window.console) { return; };
firebug=document.createElement('script');
firebug.setAttribute('src','http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js');
document.body.appendChild(firebug);
(function(){if(window.firebug.version){firebug.init();}else{setTimeout(arguments.callee);}})();void(firebug);
}


Вот и все магия о которой я хотел вам рассказать.

Эта моя последняя статья в этом году :). Хочу всех поздравить с Новым Годом. И пожелать, чтобы наступающий год принес вам больше счастья и радости, чем позволят ваши самые смелые желания!

1 комментарий:

  1. Как можно работать с чужим кодом? Есть какой-то элемент, как его "следить"? т.е. смотреть какие на нем ивенты навешаны/вызываются и тд

    ОтветитьУдалить