Как стать автором
Обновить

Комментарии 23

Не успел добавить это в статью. Но так даже лучше, все сайты который нагло копируют контент с хабрабахабра не получат эту мелочь:
Firebug, в отличае от Chrome не понимает символа перевода строки "\n", который идёт сразу после паттерна в console.log.
Пример
console.log('%s\n%s','первая','вторая');
console.log('%s \n%s','первая','вторая');
Скриншоты
new line
Прибавлю: console.timeEnd() не просто останавливает указанный таймер, но и выводит в консоль количество прошедшего времени (в миллисекундах).
Спасибо. Добавил в статью.
Интересный материал, всегда использовал только «console.log», не знал о таких возможностях, спасибо!
3 недели назад я тоже о них не знал (:
Статью написал как раз по той причине, что в интернете нету толкового мануала. Так что я сам буду сюда подглядывать ещё не раз.
Рад что и вам она оказалась полезной.
На самом деле, в отдельно взятой части интернета это всё есть:
habrahabr.ru/post/114483/
habrahabr.ru/post/50445/
, но Ваш сборник хорошо систематизирован и будет очень полезен.
Отдельно можно упомянуть о модификаторах вывода консоли:
habrahabr.ru/post/116852/
ещё ряд, отыскивается поиском,
удалённая консоль: jsconsole.com/
Небольшой код:
var wcl = function(a){ a = a!==undefined ? a :''; //консоль как метод строки или функция
	if(window.console && settings.erLevel <=2)
        Function.prototype.apply.call(console.log, console, this instanceof String
			? ["'=="+ this +"'"].concat([].slice.call(arguments))
			: arguments);
    if(cons0 && settings.erLevel <=2){
        cons.innerHTML += (this instanceof String
        		? ["<i class=consLog>'=="+ this +"'</i>"].concat([].slice.call(arguments))
        		: [].slice.call(arguments)
            ).join('<i class=consDelim>/ </i>') +'<br>';
    	cons.scrollTop = Math.max(0, cons.scrollHeight - 700);
    }
};
String.prototype.wcl = wcl;
//(позволяет писать ''.wcl(список для вывода); и выводить в консоль или плавающий див, если в браузере нет консоли)
Как дела с поддержкой всех прелестей в IE?
Почему нет упоминания об Internet Explorer? В нем тоже потихоньку развивается console.
Под рукой только winXP, а в ней нету поддержки IE 9 и 10. А тестировать в IE8 уже не вижу особого смысла. Примеры с Opera dragonfly тут только от большого уважения к данной компании.

З.Ы. По поводу IE, на хабре как-то публиковался обзор расширения, добавляющего более менее вменяемую поддержку console API в него.
А в Safari что с этим?
Тоже не имею возможности проверить. Но если я правильно понимаю, то в нём тот же WebDev Tools что и в Chrome
Тогда это уже самому. В Safari другие WebDev Tools, они отличаются от тех что в Chrome и других Webkit (фирменные Apple).
пробуйте в своё удовольствие

весь код из примеров
var a = 'один аргумент';
console.log(a);
console.log('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.log('Node', document.getElementsByTagName('body'));
console.log('DOM', document);
console.log('функция', alert);
console.log('прочее', NaN, null, undefined);

console.log('У Пети было %d %s',10,'яблок');
console.log('Пи равно %f',Math.PI);
console.log('%cКаждый %cОхотник %cЖелает%c знать где сидит фазан','color:red;','font-size:16px;color:orange;','background:black;color:yellow;','font:normal;color:normal;background:normal;');
console.log('body as DOM: %o',document.getElementsByTagName('body')[0]);
console.log('object: %O',{a:1,b:2});
console.log('body as Object: %O',document.getElementsByTagName('body')[0]);

console.assert(2>1);
console.assert(1>2);
console.assert(2>1,'выражение истинно');
console.assert(1>2,'выражение ложно');
console.assert(1>2,'выражение','ложно');
console.assert(1>2,'провека паттернов: [%s]','провалена');
console.assert(1>2,'много','аргументов',1,2,3,{a:1});

console.count();
console.count(); // уже другой счётчик
console.count('первый');
console.count('первый'); // тот же счётчик только для Chrome
console.count('много','разных','аргументов');
console.count(document);
for (i=0;i<2;i++) console.count(); // один и тот же счётчик
for (i=0;i<2;i++) console.count('второй'); // один и тот же счётчик

var a = 'один аргумент';
console.debug(a);
console.debug('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.debug('Node', document.getElementsByTagName('body'));
console.debug('DOM', document);
console.debug('функция', alert);
console.debug('прочее', NaN, null, undefined);
console.debug('У Пети было %d %s',10,'яблок');

console.dir('простой элемент');
console.dir([1,2]);
console.dir({a:1});
console.dir([1,2],{a:1});
console.dir(document);

console.dirxml('простой элемент');
console.dirxml([1,2]);
console.dirxml({a:1});
console.dirxml(document);
console.dirxml([1,2],{a:1});


console.error(); // без аргументов
console.error('ошибка с комментарием');
console.error('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.error('У Пети было %d %s',10,'яблок');
(function firstlevel () {
    (function secondlevel () {
        (function lastlevel () {
            console.error('проверка стэка');
        })();
    })();
})();
console.error(new Error('настоящая ошибка')); //  настоящая ошибка

console.exception(); // без аргументов
console.exception('ошибка с комментарием');
console.exception('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.exception('У Пети было %d %s',10,'яблок');
(function firstlevel () {
    (function secondlevel () {
        (function lastlevel () {
            console.exception('проверка стэка');
        })();
    })();
})();
console.exception(new Error('настоящая ошибка')); //  настоящая ошибка

console.log('Текст вне групп');
console.group(); // без аргументов
    console.log('Текст в безымянной группе');
    console.group('первая группа', 'со', 'множеством', 'аргументов', 12, true, [1,2,3], {a:1,b:2});
        console.log('Текст в первой группе');
        console.group('вторая %cгруппа', 'color: red;');
            console.log('Текст во второй группе');
            console.groupCollapsed('третяя группа');
                console.log('Текст в третьей группе');
            console.groupEnd();
            console.log('Текст во второй группе');
        console.groupEnd();
        console.log('Текст в первой группе');

var a = 'один аргумент';
console.info(a);
console.info('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.info('Node', document.getElementsByTagName('body'));
console.info('DOM', document);
console.info('функция', alert);
console.info('прочее', NaN, null, undefined);
console.info('У Пети было %d %s',10,'яблок');

console.profile();
(function someFunction() {
  for (i=0;i<10000000;i++) {var s='a'; s+='a'; delete s;}
})()
console.profileEnd();
console.profile("мой профиль");
(function someFunction() {
  for (i=0;i<10000000;i++) {var s='a'; s+='a'; delete s;}
})()
console.profileEnd();

var table = [];
table[0] = [1,'2',[1,2,3]];
table[1] = [document,document.getElementsByTagName('body'),window];
table[2] = [{a:1},null,alert];
console.table(table);

function Person(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}
var family = {};
family.mother = new Person("Ольга", "Иванова", 32);
family.father = new Person("Иван", "Иванов", 33);
family.daughter = new Person("Дарья", "Иванова", 5);
family.son = new Person("Олег", "Иванов", 8);
console.table(family);

console.timeStamp();
console.time('мой таймер');
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.time('мой второй таймер');
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd('мой второй таймер');
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd('мой таймер');
console.timeStamp('второй таймстамп');
console.time(12);
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd(12);
console.time(document.getElementsByTagName('script'));
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd(document.getElementsByTagName('body'));
console.time(1,2,3); // много аргументов
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd(1,3,2);
console.time(); // без аргумента
(function someFunction() {for (i=0;i<1000000;i++) {var s='a'; s+='a'; delete s;}})()
console.timeEnd();
console.timeStamp('последний таймстамп');

console.trace();
(function firstlevel () {
    (function secondlevel () {
        (function lastlevel () {
            console.trace('проверка стэка');
        })();
    })();
})();

var a = 'один аргумент';
console.warn(a);
console.warn('много аргументов', 12, true, [1,2,3], {a:1,b:2});
console.warn('Node', document.getElementsByTagName('body'));
console.warn('DOM', document);
console.warn('функция', alert);
console.warn('прочее', NaN, null, undefined);
console.warn('У Пети было %d %s',10,'яблок');

console.log('%s\n%s','первая','вторая');
console.log('%s \n%s','первая','вторая');
Монументальненько. Сколько ж сил ушло на то, чтобы все эти скриншоты (спрятанные за два клика) сделать…
Благодаря Vendict узнал, что после 12.15 вышла ещё одна последняя версия на presto — 12.16
Но исходя из changelog никаких изменений в Dragonfly не было. Так что все примеры с Opera так же актуальны.
Это очень круто, спасибо.
Единственное что не понятно, почему апи консоли без событий?

Очень пригодилось бы для селениум тестов отлавливать, если warn, например, проскакивает.
console.log — у вас там стоит плюс для Хрома, но я бы поставил плюс-минус. Для меня важно, чтобы эти примитивы консоли также были полноправными функциями, потому что это удобно при отладке: я могу передавать .log, .warn, .info, .dir в качестве коллбека без необходимости писать (если вдуматься, то абсолютно бессмысленную) обвязку в духе:
function log (...)
{
   console.log(...);
}

В Хроме же я получаю Illegal invocation при попытке сделать call / apply на примитивах консоли. В Фаирфоксе (и Баге) же эти полноправные функции можно вызывать даже в отвязке от объекта console.

Мне этот небольшой недостаток Хрома периодически припекает, и, кстати, является одной из ряда мелких причин почему я предпочитаю Фаирбаг, несмотря на всю его тормознутость.
Весьма дельное замечание! Если опишете подробнее с примерами — добавлю в статью, думаю такая информация может пригодиться.
Собственно, я уже описал то, что хотел. Суть в том, что объект console может быть реализован по-разному в разных средах. В некоторых случаях объект реализуется с полноправными, хоть и нативными функциями, то есть если попробовать вывести console.log.toString(); мы получим вместо исходного кода функции [native code]. В некоторых средах, насколько я понял, этот объект просто предоставляет штуки, которые можно вызывать с круглыми скобками, но они не являются полноправными функциями: их нельзя вызвать с call / apply / bind. Из примеров: отладчик Хрома и отладчик ИЕ.
Основной минус:
Пусть есть EventEmitter и мы хотим прологировать его активации. Для этого достаточно подписать какой-нибудь логгер на него, например console.log.
object.on('event', console.log);

То есть будет вызван console.log со всеми параметрами, с которыми вызывается любой коллбек на этом эмиттере. Можно заменить это на console.dir, тогда в некоторых средах (Node.js) будет более подробный вывод первого параметра. В любом случае, если console.log, console.dir не будут функциями, то их нельзя будет вызвать, придётся писать обвязку. Причём в случае console.log обвязка будет неполноценная: мы не сможем передать все параметры, потому что мы не можем сделать apply.
function log (a1, a2, a3) {
   console.log(a1, a2, a3); // нельзя использовать arguments, потому что нельзя сделать apply
}

А разгадка одна — безблагодатность.
В общем, функции должны быть функциями.
Добавил в пост.
console.clear() в firefox developer tools это заглушка, она ничего ничего не делает, консоль не очищается.
На момент написания статьи в firefox developer работало. Так или иначе спасибо за комментарий.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории