Отладка Javascript — Console

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

Отладчики Javascript

  • firebug — Mozilla Firefox
  • Chrome developer tools — Chrome, Safari
  • Dragonfly — Opera
  • Developer Tools, Microsoft Script debugger — IE
  • Firebug light (https://getfirebug.com/firebuglite) — cross browser

По личному опыту мне близок firebug. Именно этот инструмент был одним из первых действительно полезных отладчиков.

Отладочная панель в Chrome обладает очень большим объемом возможностей но требует времени на освоение и привыкание. Данный инструмент заслуживает отдельной публикации.

Opera всегда была «особенным» браузером. Даже если вам кажется что dragonfly это какой то «унылый капец» — вы очень заблуждаетесь. Без этого инструмента отладка многих «специфичных» для Оперы вещей станет ночным кошмаром.

Об отладчиках под IE можно спорить долго, но если вы не занимаетесь поддержкой IE6, то Developer Tools покроет большинство ваших нужд по отладке в этом «гениальном» творении microsoft.

Firebug light обладает достаточно скромными возможностями, но, может вас очень выручить во многих случаях. В основном, когда нет возможности использовать один вышеупомянутых отладчиков.

Немало полезной информации вы можете найти здесь http://learn.javascript.ru/browsers

Console

console — это не стандарт, так что не факт что заработает везде. В некоторых браузерах console доступен только при открытом/включенном отладчике, например firebug, dragonfly, в других консоль доступна всегда, например chrome. Я, иногда, встречаю конструкции типа

if(window.console !== undefined){
..........
}

Если вы планируете таким образом отключить отладочные операции при выключенном отладчике — вы ошиблись. Это тоже не везде работает.

Вот тут Examples вы можете опробовать приведенные мною примеры. Перейдя по ссылке не забудьте открыть отладчик прежде чем начнете «жмакать».

Методы вывода в консоль

  • console.debug(myVariable)
  • console.log(myVariable);
  • console.info(myVariable);
  • console.warn(myVariable);
  • console.error(myVariable);
  • console.table(myArray);

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

(function(){
  var myVariable = 'test';
  var myVariable1 = 20;
  var myVariable2 = 1.5;
  var myObject = {qwerty:1,asdfgh:2};
  console.log(
    'My string variable is: "%s";\nMy int variable is:"%i"\nMy Float Variable is: "%f"\nMy Object is: "%o"',
    myVariable,
    myVariable1,
    myVariable2,
    myObject
 );
})();

Вполне второй вывод ощутимо нагляднее, не правда ли? То же самое для объекта:

(function(){
  var cars = {
    'chevrolet aveo':{name: 'aveo', vendor:'chevrolet'},
    'renault logan':{name: 'logan', vendor:'renault'},
    'hyundai accent':{name: 'accent', vendor:'hyundai'},
    'zaz forza':{name:'forza', vendor:'zaz'}
  }
  console.log(cars);
  console.table(cars);
})();

Если вааши объекты-строки отличаются набором свойств console.table обработает и такую ситуацию. Порадовала возможность указать какие именно свойства нам нужны в выводе функции:

(function(){
  var cars = {
    'chevrolet aveo':{name: 'aveo', vendor:'chevrolet'},
    'renault logan':{name: 'logan', vendor:'renault'},
    'hyundai accent':{name: 'accent', vendor:'hyundai'},
    'zaz forza':{name:'forza', vendor:'zaz'}
  }
  console.table(cars, ['name']);
})();

Функция console.debug помимо вывода указанных переменных выбросит в консоль файл и строку из которой была вызвана(справа). Впрочем, в некоторых отладчиках метод console.log тоже покажет эту информацию, некоторые источники говорят о том, что console.debug это deprecated метод, который просто является алиасом для console.log. Функции log, warn, info и error, Помогут вам разукрасить консоль при отладке, что порой прибавляет читабельности логам.

Подстановка аргументов в строку происходит по следующим правилам:

  • %o – для ссылки на объект
  • %d, %i – целые чила (integer)
  • %s – строки
  • %f – числа с плавающей запятой (float)

Метод console.table заслуживает отдельного внимания. Он предназначен для более наглядного логирования массивов и прочих структур в табличном виде. Попробуйте запустить в консоли вот этот пример

(function(){
    var cars = [
        {name: 'aveo', vendor:'chevrolet'},
        {name: 'logan', vendor:'renault'},
        {name: 'accent', vendor:'hyundai'},
        {name:'forza', vendor:'zaz'}
    ]
    console.log(cars);
    console.table(cars);
})();

Вывод console.table ощутимо нагляднее не правда ли? То же самое для объекта:

(function(){
  var cars = {
    'chevrolet aveo':{name: 'aveo', vendor:'chevrolet'},
    'renault logan':{name: 'logan', vendor:'renault'},
    'hyundai accent':{name: 'accent', vendor:'hyundai'},
    'zaz forza':{name:'forza', vendor:'zaz'}
  }
  console.log(cars);
  console.table(cars);
})();

 

Даже если ваши объекты-строки содержат разный набор свойств. Эта функция отработает, просто некоторые столбцы будут содержать undefined.

Для логирования элементов дома стоит использовать методы

  • console.dir() — Покажет свойтва элемента
  • console.dirxml() — Покажет html-код элемента

Так же полезными могут оказаться методы группировки выводов в консоль

  • console.group({groupName})
  • console.groupCollapsed({groupName})
  • console.groupEnd()

Например:

(function(){
  console.groupCollapsed('test_debug')
  var myVariable = 'test';
  var myVariable1 = 20;
  var myVariable2 = 1.5;
  var myObject = {qwerty:1,asdfgh:2};
  console.log(
    'My string variable is: “%s”;\nMy int variable is:"%i"\nMy Float Variable is: "$f"\nMy Object is: “%o”',
    myVariable,
    myVariable1,
    myVariable2
  );
  console.groupCollapsed('document_body')
  console.dir(document.body);
  console.dirxml(document.body);
  console.groupEnd();
  console.groupEnd();
})();

Если вам нужно измерить время выполнения какого либо кода можно воспользоваться методами таймера

  • console.time({timerName});
  • console.timeEnd({timerName})

Например:

(function(){
  console.groupCollapsed('test_debug');
  console.time('execution_time');
  var myVariable = 'test';
  var myVariable1 = 20;
  var myVariable2 = 1.5;
  var myObject = {qwerty:1,asdfgh:2};
  console.log(
    'My string variable is: “%s”;\nMy int variable is:"%i"\nMy Float Variable is: "$f"\nMy Object is: “%o”',
    myVariable,
    myVariable1,
    myVariable2
  );
  console.groupCollapsed('document_body')
  console.dir(document.body);
  console.dirxml(document.body);
  console.groupEnd();
  console.timeEnd('execution_time');
  console.groupEnd();
})();

Можно запускать несколько таймеров на разные части кода различая их по метке(любая осмысленная строка). Ещё один полезный метод отладки кода — профилирование.

  • console.profile()
  • console.profileEnd()

Так же вам может здорово пригодится метод console.trace() В случаях, когда нужно понять цепочку вызовов до конкретного метста в коде. Это не все методы объекта console предоставляемые отладчиком firebug. Более полный список можно найти здесь: https://getfirebug.com/wiki/index.php/Console_API

Поддержка функционала console отличается в разных браузерах и разных отладочных инструментах. Проверить какой функционал поддерживается можно выполнив метод console.dir(console). Который покажет вам свойства объекта console.

Console и ассинхронный javascript.

Ассинхронный javscript живет обособленной жизнью, что может создать определенные проблемы при отладке. В качестке примера можем опробовать вот такой фрагмент кода.

(function(){
  console.groupCollapsed('test');
  $.ajax({
    url:'http://google.ru',
    beforeSend:function(){
      console.log('Sending ajax request');
    },
    error:function(){
      console.log('Error receiving data');
    },
    success:function(data){
      console.log('Ajax responce received');
    }
  });
  console.groupEnd('test');
})();

Если вы выполнили этот фрагмент кода, то должны были заметить, что лог из функций success и error выпадает вне группы. Это происходит потому что в данном случае javascript работает асинхронно и к моменту срабатывания методов success или error группа уже закрыта.

Решение данной проблемы зависит от вашей фантазии. Один из вариантов это собрать все логи и вывести их уже когда вернется ответ из ajax, но существуют и другие варианты. Вероятно я соберу разного рода «хитрости» в отдельной публикации.

Собственный объект.

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

var MyDebug = (function (){
  return {
    isOn: false,
    log: function() {
      if (this.isOn && window.console)
      console.log.apply(console, arguments);
    },
    debug: function() {
      if (this.isOn && window.console)
      console.debug.apply(console, arguments);
    },
    stop: function() {
      if (this.isOn) debugger;
    }
  }
})();

Это маленький фрагмент «на лету». Но многим разработчикам уже приходилось решать подобную задачу. Если вы всерьез задумались о расширении и кастомизации объекта console то советую прочитать вот этот пост. Готовую реализацию можно найти здесь.

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

(function(){
  function createCar(carModel){
    var hello = 'My Model is: ';
    return new function(){
      this.getModel = function(){
        return hello + carModel;
      }
    }
  }

  var car = createCar('ZAZ Forza');

  console.log(car.%carModel);
  console.log(car.%hello);
  console.info(car.getModel());
})();

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

Достаточно интересную фитчу подсказал Степан в комментарии. Консоль позволяет использовать стили в выводе. Достаточно подробно можно почитать например тут. В прочем, мне не приходилось использовать данный функционал. Было достаточно использования разных функций логирования.

P.S. Хочу выразить благодарность Stepan Suvorov за наводку на некоторые полезные материалы.

4 комментария

Добавить комментарий