Функция К.O'Nsole.log для отладки в разных браузерах

    Хорош console.log, а нахваливать дальше некуда. И поддерживается не везде, и многобуквием страдает. И появляется задача иметь несложную функцию, настолько же гибкую, как console.log (или более), но приспособленную к разным браузерам без переделок, чтобы вывести одно или несколько значений. В отладке часто нужны текстовые поясняющие заголовки в строке, поэтому оказалось удобным иметь метод, добавленный к строке (объект String) с именем Alert, выполняющий то же самое, что и console.log и выводящий контекст-строку впереди списка аргументов. (Строку в апострофах, потому что удобно затем копировать и искать по кодам, где такой заголовок написан.)

    Углубляться в многообразие команд в реализациях каждого браузера оказывается ненужным, потому что это теряет смысл при проверках в другом браузере. А долгое допиливание идеального продукта — попросту невыгодно, требует профессионального углубления в особенности и слежения затем за новинками, ошибками и их устранением. Нужна совершенно простая схема работы, которая легко доработается, если что-либо надо дополнительно и использующая базовые возможности консолей отладки.

    Система чуть сложнее, чем доопределение самого console.log (внутренняя функция alertInner), и имеет такие достоинства:
    1) новых слов всего 2, и те — знакомы;
    2) слова — короче, чем К.О'Ns… (и т.д.);
    3) не замещает других используемых имён,
    4) гораздо проще других сложных скриптов,
    5) код легко читается и кастомизируется.

    Обычный alert() в этой системе участвует как наихудшая альтернатива вывода. Но и он может за один раз выдать несколько значений, разделённых запятой (например, в IE8 без включённого DebugBar-а).

    Часто требуются 2 основных действия: запретить всю отладку одной командой; отключить бОльшую часть отладки, если вынужден смотреть алерты в малых объёмах или просто есть желание посмотреть часть сообщений. Строки-контексты для этого хорошо подходят. Будем включать только те сообщения, в заголовках которых найдутся образцы (жадного) регулярного выражения:

    Alert.go =''; //- разрешить все; аналог типичного DEBUG = true; , но без лишней переменной;
    Alert.go ='.'; //- разрешить только методы-Алерты, кроме ''.Alert() (простые функции Alert запрещены искусственно по признаку - так удобно, исключение 1);
    Alert.go ='.*'; //разрешить и с пустой строкой, но без простых алертов, исключение 2;
    delete Alert.go; //- запретить все;
    Alert.go ='fthghhfgh'; //запретить методы-Алерты;
    Alert.go ='^(aab|xaa==|test45:|xxx|__)$'; //- выполнять только перечисленное (и функции-Алерты).
     
    (Для удобства в код вшиты 2 исключения и 1 кастомизация. Последнюю можно выбросить или наоборот, развить, но исключения — полезные и понятные. Надо иметь весь спектр действий: запретить всё, разрешить функции, разрешить методы, разрешить то и другое, разрешать методы с фильтром и без — не увеличивая систему команд.)

    Запускаем:
    Alert(aaa, bbb,'==переменные==', ссс); //обычный аналог console.log()
    'xaa=='.Alert(xaa, xx.element, xaa(1)); //всё, что хотим - под своим заголовком в начале строки
    '-test-'.Alert('вывод текста самого себя, например', Alert);
    

    Таким образом, запускать на разных отладочных страницах разные выдачи оказывается удобно и наглядно. Инструмент остаётся крайне простым (всего 3 функции под одним именем, каждая из которых знакома и востребована), хотя есть резервы повышения монстрообразности — если в контекст ставить имя функции-обработчика или хеш, описывающий таблицу выдачи, можно далеко зайти. Или, например, я добавил в код ососбый вывод для сообщений вида Alert({from:'-test-', xx: прочие параметры… });. Обычно этот формат не нужен, т.к. забывается; но плюс его в том, что первый аргумент, хеш — просматривается разобранным, иногда бывает нужен для показа в простых алертах и в HTML.

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

    Для консоли раньше в Опере нужно было так, сейчас не обязательно (есть Dragonfly-консоль, Ctrl-Shift-I, затем значок ">_"):
    ...else if (window.opera && opera.postError) {opera.postError(arguments);}

    … Недавно тут FF5 (или firebug?) испортил картину, отказавшись понимать console.log.apply, пришлось дописать некрасивую альтернативу. Как обойти баг, не придумал, да и не обязательно. Редко число аргументов больше 7 и всегда их можно собрать в массив.

    Код функции:
    /**
     * Функция/метод "Лог-отладка-фильтр", spmbt0, 30.07.2011
     * @context (String) : начальные слова, описывающие строку отладки
     * @property go: рег.выражение для фильтра лога или undefined, если запретить выдачу
     * @param o: аргументы, выводящиеся в 1 строке в консоли отладки
     */
    Alert = function(o){
    	if(Alert.go===undefined) return; //===быстрый общий запрет===
    
    	var alertInner = function(x, xx,a,b,c,d,e){ //x: аргументы (в FF5 - до 7, особенность Firebug для этой версии)
    		var aL = arguments.length;
    		if(!window.console){
    			for(var i =0, args =[]; i < aL; i++)
    				args[i] = arguments[i];
    			alert(args);
    		}else if(console.log.apply)
    			console.log.apply(console, arguments);
    		else{ //иначе - 5-й FF не умеет понимать console.log.apply
    			if(aL ==1) console.log(x);
    			else if(aL ==2) console.log(x, xx);
    			else if(aL ==3) console.log(x, xx, a);
    			else if(aL ==4) console.log(x, xx, a, b);
    			else console.log(x, xx, a, b, c, d, e);
    		}
    	}, hasContext = this !== window
    		, context = this;
    	if(hasContext && context instanceof String){
    		if(!RegExp(Alert.go,'g').test(context)) //===фильтрация по разрешениям===
    			return;
    		
    		for(var i =1, args =[]; i <= arguments.length; i++)
    			args[i] = arguments[i -1];
    		args[0] = "'"+ context +"':";
    		alertInner.apply(window, args); //===console.log с текстовым контекстом на первом месте===
    
    	}else{ //место для кастомизации. Пример с {from:'имя', ...}
    		if(Alert.go =='.' || Alert.go =='.*') return; //===запретить обычные алерты===
    		if(o && o.from && o.from !=''){ //если в хеше в первом аргументе есть ключ "from", он оформляется особо
    			var args =[], j =1;
    			for(var i in o)
    				if(i !='from'){
    					args[j++] = '{'+ i +'}';
    					args[j++] = o[i];
    				}
    			if(arguments.length >1) //разделитель
    				args[j++] ='}; ';
    			for(var i = 1, aL = arguments.length; i < aL; i++) //вывод следующих аргументов
    				args[j++] = arguments[i];
    			args[0] = "'"+ o.from +"':";
    			alertInner.apply(window, args); //===console.log со значение ключа "from" на первом месте===
    
    		}else
    			alertInner.apply(window, arguments); //===обычный console.log===
    	}
    }
    String.prototype.Alert = Alert;
    Alert.go =''; //разрешить всё
    //Alert.go ='test-'; //разрешить только с таким фрагментом в контексте (и все простые Alert() )
    Для просмотра получившегося содержимого в консоли — сделать:
    Firefox: при наличии Firebug — Ctrl-Shift-L (командная строка); без него — никто не знает :);
    Chrome: Ctrl-Shift-J (консоль Javascript);
    Safari: Ctrl-Alt-C (консоль ошибок);
    IE: чтобы не выводилось это алертами, открыть DebugBar или что-то аналогичное;
    Opera: сообщения видны в консоли ошибок (Ctrl-Shift-O), но там — с мусором; удобнее — в Dragonfly (Ctrl-Shift-I, затем значок ">_").

    Работу скрипта с примерами смотреть здесь: spmbt.kodingen.com/function/testAlert.htm.



    Вопрос (опрос): кто какие немонстровидные решения для отладки использует?

    *) К литературе от себя добавлю, что есть у Firebug фича, которую крайне сложно найти в описаниях, если не знаешь, как она называется. Называется она "debugger;". Если такое имя встретится в джаваскрипте, Firebug остановится как на обычном брейкпойнте, дальнейший старт программы — из вкладки «Script» кликом на «Continue (F8)».
    weirdan написал: --Эта фича есть в ECMA-262-5 и поддерживается как в Fx, так и в IE.

    0. Firebug Command Line API.
    0.1 Вышел релиз Firebug 1.8 (поддерживается в Firefox 5.0). Детальная информация (на Хабре) по новым возможностям версии.

    О консоли на Хабре:
    1. «Отладка Javascript в различных браузерах и средах», 24 января 2009, lomaster
    2. Используем console на полную, 26 февраля 2011, Ryan Seddon
    3. Удалённая отладка Javascript, 3 марта 2011, youtu.be…
    4. Современная отладка JavaScript, 7 февраля 2009, Chris Mills, Hallvor…
    5. Использование средств отладки, 27 августа 2008, Pamela Fox, Google M…

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 16

      +13
      Скажу честно: как мне кажется, единственная реально полезная обертка над console.log — это ф-я, которая не прекращает работу всех скриптов на сайте из-за забытого вызова console.log :)

      Я знаю, по крайней мере, 2 варианта решения проблемы с забытым console.log():

      первый:
      if(!window.console) window.console = { log: function() {} };
      

      второй:
      function log() {
      try { window.console.log.apply(window.console, arguments) }
      catch(e) { }
      }
      


      С первым, по-моему, есть некоторые проблемы в IE8, где объект console исчезает и появляется в зависимости от того, открыты dev тулзы или нет (и соответственно, если они не открыты, то console.log не будет работать до перезагрузки страницы). Про то, что console.log.apply не работает в Fx5 я не знаю — я щас попробовал, вроде как работает. Возможно, нужно просто заменить arguments на Array.prototype.slice.call(arguments) и всё заработает.

      А вот откат на alert(), ИМХО, как раз-таки зло, ибо если планируется использовать эту библиотеку в продакшне, то за этот самый alert() юзвери вам скажут большое-пребольшое спасибо, если вдруг кто-то забудет вызов вашей Alert()
        0
        Ну и другие очень полезные, но редко используемые методы console, вроде console.dir, ИМХО, зря стороной обошли
          0
          Обошёл, потому что они не кроссбраузерные, Хром и FF имеют, остальные придётся изображать теми же логами. Это очень дезориентирует, когда стоит задача — проверить одинаковость работы в браузерах. В продвинутой оболочке ты получаешь выводы их нескольких команд, в остальных оказывается, что надо ещё что-то дописать в отладку. Лучше сразу писать то, что будет видно везде (правда, для алертов это всё равно не верно).

          О защите продакшна. Эта система, с алертами, придумана для проекта, который ещё не на продакшне, поэтому совсем некритично оставлять сообщения. Но и это предусмотрено. Первое: общий запрет. Если не писать никаких Alert.go, ни одна команда не сработает, будь даже весь проект — из команд отладки. Начнёт работать только страница, на которой мы разрешим Алерты. Разрешение — по имени хоста localhost, по имени юзера, если они в системе есть. Правильно напишете разрешения (это 1-3 строчки на странице, правда, страниц много) — алерты не пройдут.

          Наконец, ничто не мешает полностью удалить alert() (он вообще в 1 строчке проекта) и заменить выводом в DIV, потратив ещё 20-30 строк. Почему не 10? Потому что надо обойти случай сообщений до ready, накапливать куда-то в буфер. И вообще, позаботиться о качестве и информативности. Когда-то писал такое для IE6 и выше, но забросил там, где писал. Ничего там сложного нет, кроме особенностей DOM. Но и этот вывод может испугать пользователя и блокировать его работу, если не позаботиться об элементарном перехвате :).

          IE8 — да, ведёт себя так — сыплет алертами. Причём, если DebugBar закроешь, снова к алертам не переходит до перезагрузки бр-ра. FF3.6 тоже — если Firebug не открыт, посылает алерты. 5-й — ничего не сыплет, пока не откроешь Fifebug, тогда начинает идти в консоль. Но писали про баг с 4-м FF этого рода — то ли алерты сыплет, то ли ошибки. Вот в этом зоопарке и приходится отлаживать. Тем не менее, такая функция — наиболее удобна по своей простоте и выключаемости. Кроме того, в выключенном состоянии работает быстро (проверка своего 1 свойства — и назад).

          Баг с FF5 был на Win7/64. Наверное, и есть, если не было какого0то тихого обновления (они сейчас есть в Фоксе?). Сейчас проверил на WinXp/FF5 — бага нет. Может, это был баг Firebug, его недавно обновляли (добавили баги новые! :) ). Проверяется строчкой Alert(1,2,3,4,5,6,7,8); Если нет «8» — есть баг. На работе был, надо завтра будет проверить его ещё раз и Ваше предложение по правке.
          +3
          Ну и кстати в Fx начиная с 4 версии есть встроенная веб-консоль, которая вызывается, кажется, но Shift+Ctrl+K (Shift+Cmd+K). По крайней мере, она так не течет, как firebug :)
            0
            А чем это плохо?:
                    
            log : function(v){
                if (typeof console != 'undefined') return console.log(v);
            },
            
            +2
            есть у Firebug фича, которую крайне сложно найти в описаниях, если не знаешь, как она называется. Называется она «debugger;».

            Эта фича есть в ECMA-262-5 и поддерживается как в Fx, так и в IE.
              0
              Спасибо, ученье — свет :). Так и напишу. Однажды забыл её название и не мог вспомнить с поисковиком :).
                +2
                Она работает во всех популярных браузерах.
                0
                Спасибо, ученье — свет :). Так и напишу. Однажды забыл её название и не мог вспомнить с поисковиком :).
                  0
                  Хм, сообщение минуту-другую не отображалось, поэтому запустил ещё раз.

                  Вышел Firebug 1.8, blog.getfirebug.com/2011/07/29/firebug-1-8-0/, ещё 29-го, на Хабре об этом нет. Только в пятницу думал, когда исправят привнесённые в 1.7.3 баги.
                  0
                  Класс, спасибо!
                    +1
                    Спасибо, ваша статья — хорошая база для моей будущей. У меня более монструозное решение, которое однако включает кроссбраузерную поддержку console.dir (что там, всего лишь рекурсивная функция), а также уйму настроек, которые могут облегчить вывод информации на экран или в консоль. Функция сама смотрит когда ей вызываться рекурсивно, а когда как console.log.
                    При её написании обнаружил 2 бага в firebug, один пофиксили в версии 1.8, один я ещё не засабмитил (работа не волк).
                    Надеюсь что на следующей неделе появится время на статью.
                      +2
                      Как-то на хабре проскакивал Blackbird.js — кроссбраузерная консоль.
                      http://www.gscottolson.com/blackbirdjs/
                          +2
                          … Недавно тут FF5 (или firebug?) испортил картину, отказавшись понимать console.log.apply, пришлось дописать некрасивую альтернативу. Как обойти баг, не придумал, да и не обязательно.

                          Я сделал так:
                          Function.prototype.apply.call(original[methodName], original, arguments);
                          
                            0
                            Лично я для себя написал такую вот обертку:

                            1. function log(){ return myconsole._console('log',arguments); }
                            2. function info(){ return myconsole._console('info',arguments); }
                            3. function warn(){ return myconsole._console('warn',arguments); }
                            4. function error(){ return myconsole._console('error',arguments); }
                            5.  
                            6.  
                            7. myconsole._console = function (f,args){
                            8.     if (!console) return;
                            9.     try{
                            10.         console[f].apply(console,args);
                            11.     }catch(IEFuckingConsole){
                            12.         for (var i=0,l=args.length;i<l;i++){
                            13.             if (f=='log')
                            14.                 myconsole.dump(args[i]);
                            15.             else
                            16.                 console[f](args[i]);
                            17.         }
                            18.     }
                            19. };
                            20.  
                            21. myconsole.dump = function(o){
                            22.     if(typeof o == 'string')
                            23.         return console.info('-DUMP: ',o);
                            24.     var ss;
                            25.     s = o+"\n{\n";
                            26.     for (var i in o){
                            27.         if (typeof o[i] == 'function')
                            28.         {
                            29.             try {
                            30.                 ss = substr(0,64).replace(/[\r\n\t]+/g,' ')+'...}';
                            31.             }catch(c){
                            32.                 ss = 'function(){...}';
                            33.             }
                            34.         }
                            35.         else
                            36.             ss = o[i];
                            37.         s += "\t"+i+': '+ss+"\n";
                            38.     }
                            39.     s+="}";
                            40.     console.clear();
                            41.     console.info('DUMP: ',s);
                            42. };
                            43.  


                            myconsole.dump — чтобы в IE хоть как-то получить представление об объекте, а не просто запись
                            Журнал: [object Object]

                            Only users with full accounts can post comments. Log in, please.