πŸ“œ ⬆️ ⬇️

Javascript console API

It is convenient for developers to use the console for debugging, but it is even more convenient if there is a shell that takes into account the implementation features of the console in various browsers, so the console wrapper theme persists.

Consider previously published solutions, then review the console methods using the translation of a recent article by Axel Rauschmayer, a developer and consultant with more than 15 years of experience, then I will publish some of my solutions that were successful in the process of evolution and debugging on a number of projects.
UPD 2015: updating the command table to the current state , Github (ru, en; expanding to javascript).

Console wrappers on HabrΓ©, reviews and documentation


" We use the console" to the fullest " " - it shows the ways of excellent processing of objects, taking into account the features of various browsers in the implementation.

Making the console a little more convenient - Replaces the original object, which solves some bugs. Perfectly corrects the degradation of some browsers in the completeness of support methods Remains perhaps that the length of writing native methods, which is a plus in terms of not learning new names, but requires a set of original words. It can be solved by emmet type accelerators in the IDE.
')
simple wrapper for console.log - 2010 (English).
Console.Log: Say Goodbye to JavaScript Alerts for Debugging! (IE), 2011 (English)
dbug - a console wrapper (Github, 2009)
" Firebug * console API " - this article is somewhat fuller than the subsequent translation. Both will provide complementary information. (We will use the translation in order not to self-test manually, repeating the work done by the author.)

Translation review from the blog of Axel Rauschmayer


Summary table with sorting methods alphabetically .
In most browsers, there is a global console object with methods for logging and debugging. It is not part of the language, but has become the de facto standard, appearing first in the Firebug debugger. Since the main goal for it is debugging, it is often used in development and rarely in running code.

How is the console standardized in different browsers?


Firebug was the first to promote the console API and wiki documentation , moving closer to standardization more successfully than others. In addition, Brian Kardell and Paul Irish are working on the API specification , which in future should give better consistency of browser behavior. Until now, their rules are quite different, so this article will give a general short description. For more information, see the documentation for the various platforms.

Chrome: developers.google.com/chrome-developer-tools/docs/console-api/
Firebug: getfirebug.com/wiki/index.php/Console_API
Firefox: developer.mozilla.org/en-US/docs/Web/API/console
IExplorer: msdn.microsoft.com/en-us/library/ie/hh772183.aspx
Node.js: nodejs.org/api/stdio.html
Safari: Safari Developer Guide

IE9 bug : the console object exists if at least once the Developer Tools (F12) window has been opened. Otherwise, a ReferenceError error occurs. As an option to bypass the bug, you need to check the presence of the object and put a stub in case of absence.

Methods for simple logging


console . clear () - clear the console;
console . debug (object1, object2 ?, ...) is the same as console . log () (questions mean that the argument is optional) ;
console . error (object1, object2 ?, ...) - logging parameters under the error icon (without stopping the code) and, possibly, adding a call stack trace and a link to the code.
console . exception (errorObject, object1 ?, ...]) [Firebug only] - objects with an interactive trace stack;
console . info (object1 ?, object2 ?, ...) - logging to the console; browsers may be marked with and may have a stack trace or link; printf templates are supported, as in console.log.
console . log (object1 ?, object2 ?, ...) - logging to the console. If the first argument is a string in the format of printf directives, it formats the values ​​of the remaining arguments. Example (Node.js REPL):
> console.log('%s', { foo: 'bar' }) [object Object] > console.log('%j', { foo: 'bar' }) {"foo":"bar"} 

The only reliable cross-platform formatting directive is '% s'. Node.js supports '% j' for JSON data. Browsers can support other interactive action directives for the console (read more here (rus.)) .

console . trace () - showing an interactive stack of function calls in browsers (the call stack, which led to the execution of code at this point, is similar to what we see in error messages);
console . warn (object1 ?, object2 ?, ...) - logging under the warning icon; may contain a stack trace or a link. Printf templates are supported, as in console.log.

Chrome Firebug Firefox IE Node.js Safari
clear ()βœ“βœ“-⊝-βœ“-⊝-βœ“
debug ()βœ“βœ“βœ“βœ“-⊝-βœ“
error ()βœ“βœ“βœ“βœ“βœ“βœ“
exception ()-⊝-βœ“-⊝--⊝--⊝--⊝-
info ()βœ“βœ“βœ“βœ“βœ“βœ“
log ()βœ“βœ“βœ“βœ“βœ“βœ“
trace ()βœ“βœ“βœ“βœ“βœ“βœ“
warn ()βœ“βœ“βœ“βœ“βœ“βœ“


Methods for checking and counting


console . assert (expr, obj?) - if the first argument is false, then displays the object in the console and throws an exception; if true - does nothing;
console . count (label?) - counts the number of times the function has encountered this label.

Chrome Firebug Firefox IE Node.js Safari
assert ()βœ“βœ“-⊝-βœ“βœ“βœ“
count ()βœ“βœ“-⊝-βœ“-⊝-βœ“


Methods for logging with formatting


console . dir (object) - displays a representation of the object in the console. It can be interactive - unfold, view in other tabs of the tool (in Node.js - without interactivity).
console . dirxml (object) - Displays the XML tree of the HTML or XML element.
console . group (object1 ?, object2 ?, ...) - starts displaying a collapsible object in the console containing groups of specified and future values ​​in each new line. The block is declared complete by the command console.groupEnd () and initially deployed for viewing, but can be minimized-unfold manually (with the mouse).
console . groupCollapsed (object1 ?, object2 ?, ...) - works like console.group (), but the block is initially minimized.
console . groupEnd () - closes the group that was started by console.group () or console.groupCollapsed ().
console . table (data, columns?) - outputs an array as a table, one element per line. An optional argument specifies which properties of the array are displayed in columns. If omitted, all properties are displayed. Non-existent properties are displayed in the columns as undefined.
  var persons = [ { firstName: 'Jane', lastName: 'Bond' }, { firstName: 'Lars', lastName: 'Croft', age: 72 } ]; //  : console.table(persons); console.table(persons, ['firstName', 'lastName', 'age']); 
We will see in the console:
(index)firstNamelastNameage
0"Jane""Bond"undefined
one"Lars""Croft"72

Chrome Firebug Firefox IE Node.js Safari
dir ()βœ“βœ“βœ“βœ“βœ“βœ“
dirxml ()βœ“βœ“-⊝-βœ“-⊝-βœ“
group ()βœ“βœ“βœ“βœ“-⊝-βœ“
groupCollapsed ()βœ“βœ“βœ“βœ“-⊝-βœ“
groupEnd ()βœ“βœ“βœ“βœ“-⊝-βœ“
table ()βœ“βœ“-⊝--⊝--⊝--⊝-


Profiling and Timing


console . markTimeline (label) - [Safari-only] is the same as timeStamp ().
console . profile (title?) - enable profiling. The optional argument is used to comment in the report.
console . profileEnd () - stops profiling and displays a report.
console . time (label) - starts a timer with the specified label (name, identifier).
console . timeEnd (label) - stops the timer with a label and shows the counted time.
console . timeStamp (label?) - displays intermediate time counts for a timer with the specified label.
Chrome Firebug Firefox IE Node.js Safari
markTimeline ()-⊝--⊝--⊝--⊝--⊝-βœ“
profile ()βœ“βœ“(devtools)βœ“-⊝-βœ“
profileEnd ()βœ“βœ“(devtools)βœ“-⊝-βœ“
time ()βœ“βœ“βœ“βœ“βœ“βœ“
timeEnd ()βœ“βœ“βœ“βœ“βœ“βœ“
timeStamp ()βœ“βœ“-⊝--⊝--⊝--⊝-

"(devtools)" means that the method will work if the developer toolbar is open.

Thanks:
Two people participated in the preparation of this review: Matthias Reuter (@ gweax) and Philipp Kyeck (@ pkyeck).
--Avtor: Axel Rauschmayer. (End of translation.)

Summary table sorted alphabetically. (Links will help to see the details and read about the support of Opera in addition to this article. Short remarks about Opera from there were added to the last column.)
Chrome Firebug Firefox IE Node.js Safari Opera
assert ()βœ“βœ“-⊝-βœ“βœ“βœ“Β±
clear ()βœ“βœ“-⊝-βœ“-⊝-βœ“βœ“
count ()βœ“βœ“-⊝-βœ“-⊝-βœ“Β±
debug ()βœ“βœ“βœ“βœ“-⊝-βœ“Β±
dir ()βœ“βœ“βœ“βœ“βœ“βœ“βœ“
dirxml ()βœ“βœ“-⊝-βœ“-⊝-βœ“Β±
error ()βœ“βœ“βœ“βœ“βœ“βœ“Β±
exception ()-⊝-βœ“-⊝--⊝--⊝--⊝-Β±
group ()βœ“βœ“βœ“βœ“-⊝-βœ“βœ“
groupCollapsed ()βœ“βœ“βœ“βœ“-⊝-βœ“βœ“
groupEnd ()βœ“βœ“βœ“βœ“-⊝-βœ“βœ“
info ()βœ“βœ“βœ“βœ“βœ“βœ“βœ“
log ()βœ“βœ“βœ“βœ“βœ“βœ“Β±
markTimeline ()-⊝--⊝--⊝--⊝--⊝-βœ“-⊝-
profile ()βœ“βœ“(devtools)βœ“-⊝-βœ“-⊝-
profileEnd ()βœ“βœ“(devtools)βœ“-⊝-βœ“-⊝-
table ()βœ“βœ“-⊝--⊝--⊝--⊝--⊝-
time ()βœ“βœ“βœ“βœ“βœ“βœ“Β±
timeEnd ()βœ“βœ“βœ“βœ“βœ“βœ“Β±
timeStamp ()βœ“βœ“-⊝--⊝--⊝--⊝--⊝-
trace ()βœ“βœ“βœ“βœ“βœ“βœ“Β±
warn ()βœ“βœ“βœ“βœ“βœ“βœ“βœ“

Thanks to the author of the blog for the latest information and tables related to the methods of the console. Charging popcorn, continue the conversation. We have all the methods to use, but most often do not need all. Often one is enough, but universal console.log. There are many tasks where modest, but cross-browser capabilities are needed.

Several snippets (code inserts with functions) for various uses


All that is higher is beautiful, it is suitable as a reference book, quite complete and good. But we need solutions, not a theory - because for every small problem, similar solutions will be needed.

Experience shows that it is not at all necessary to have comprehensive support for all functions - most often one or several is enough, and service functions are more interesting: disable the console completely with one variable or expression (when the code is laid out on the production), output only errors by variable or prepare errors for sending in technical support of the project, to have a controlled conclusion of messages in the form of several options.

Complex and non-cross-browser functions are no longer needed than needed: a nice table output that doesn’t allow debugging in IE or Safari will be more likely to get in the way and make you return to the console settings level at inappropriate moments.

Therefore, based on experience, the examples will be as simple as possible, but they work without unnecessary code. If parts of the code are not needed, it is easier to choose a less complex example for a project or page.

First we need to make our own speculations about what we need to have. Non-lovers to read someone's fabrications may leave an article on this. Based on them, examples will be constructed.

1. Design code functions.


Let's talk and choose the design code. This is not a page design; this is how the code will look in a text editor.

For debugging, we have 2 standard methods and, accordingly, design - functions of the alert / confirm / confirm / type and methods of the console object. Replacing the standard names of functions and methods is still not always good. Ea except when it is necessary to prevent implementation errors, as in IE. For my debugging, in my opinion, it is more expedient to choose another name for functions or their groups. For example, I experimented with the word "Alert", with a capital letter, but it seemed long after several projects, and I switched to "wcl ()" - a symbolic abbreviation for "window.console.log". If you do not like the choice, substitute your own version in the examples.

From wcl (), the remaining abbreviations follow logically and clearly - wci - window.console.info; wcw - window.console.warn; wce - window.console.error. Such words are rarely found in the names of the transposed ones, they are rather short and are normally found by looking or searching through the project. For timings, add wct (), and to reset the console - wcc ().

These functions are proposed to be placed immediately in the global object. This will not clutter up the space of a global object, because in a production they can, if desired, take a bite out of the project codes. And the application saves at least 2 characters or more than if they were in the object (such as C.log, C.err, ...).

At this, the design is not finished - such a trick was also quite convenient to attribute them to the methods of the String object.
 String.prototype.wcl = wcl; 
Do not rush to raise indignant hands - this is not a violation of pure principles, because it will work, again, at the stage of debugging, development. On a clean project, you can also bite them out of the code. And it helps the way that debugging messages are easy to find through Ctrl-F.
 'Ajax_request'.wcl(data); //  'Ajax_request' Object{......} // wcl('Ajax_request', data); 

Find this fragment in the code by the string " Ajax_request ' " (with an apostrophe at the end). At the beginning of the line we are free to put our additional characters to better highlight the message in the log, for example, "==".

Output design: the log is not always available in browsers. This is true not only for IE with its famous bug, but also for browsers on TVs - smart TV - technologies and cable television set-top boxes use browsers that do not have console output and are not going to have it. You have to use a remote debugger or output to a block on the screen. Ideally, if there is a variable that allows you to show or create a block, and translates the entire log to the screen. It does not hurt for IE, freeing us from tracking object missing errors.

Finally, if you need to quickly clear production from logs, you need to have an expression in the shell that prohibits the display of logs. For example, output if the domain is localhost and not otherwise. Then you do not need to remove them from the code by parsing the project, although the debugging turned off will load JS a little and increase the code.

Let us summarize the code design (it was not formed now on these reasonings, but years for 2 practices; reasoning is a way to explain the reasons for the origin and the convenience obtained).

1) we use names for logs: wcw, wci, wcl, wce, wcc, wct;
2) we will not use other opportunities - we have not grown to use, but we have grown to understand that simple is better than complex;
3) all functions can work as methods of the String object for convenience of writing in code: 'string'.wcl ();
4) can be turned off by one expression;
5) can display logs to another view - div on the screen or a remote console;
6) the possibility of dynamic flow switching for information distribution is interesting.

2. Snipples


2.1. Simple logging without IE


 var noConsole =0, win = window ,wcl = function(a){ a = a!==undefined ? a :''; //     ,    noConsole ==1 if(win.console && !noConsole) win.console.log.apply(console, this instanceof String ? ["'=="+ this +"'"].concat([].slice.call(arguments)) : arguments); }; String.prototype.wcl = wcl; 

There are a couple of elements of simple street magic: the first line of the function allows you not to specify arguments and have no errors for expressions like 'location_116'.wcl (). And the expression [] .slice.call (arguments) allows you to purchase a collection of arguments from an array property so that they can participate in the concat () operation without errors. (This is often asked at interviews: how do you turn a collection into an array?)

If you decide to abandon the object's properties altogether, it turns out quite briefly (the question here is in the design of the code, will the writing in the wcl (...) format suit us):
 var noConsole =0, win = window ,wcl = function(){ //     ,    noConsole ==1 if(win.console && !noConsole) win.console.log(arguments); }; 
We do not check the absence of arguments, since we simply will not use β€œwcl ();” without arguments. It will work in IE, if the developer tools window is open.

2.2. Simple logging with IE


IE’s misunderstanding that console.log is a function leads to another round of magic (and, in general, slows down a bit in all browsers, so it’s better to use it if you really need IE).
 var noConsole =0, win = window ,wcl = function(a){ a = a!==undefined ? a :''; //     ,  .  noConsole ==1, +IE if(win.console && !noConsole) Function.prototype.apply.call(console.log, console, this instanceof String ? ["'=="+ this +"'"].concat([].slice.call(arguments)) : arguments); }; String.prototype.wcl = wcl; 


2.3. Four levels of log messages


If we want to color the output a little, in order to distinguish the importance and nature of the messages of our project, we will use copyright using the code written in 2.1 to work 4 similar and all supported functions - log, warn, info, error. Since the copywriter in the code is not the best, albeit a simple method, we will copy the next snippet where the copywriter has already been converted into a loop, and an interesting feature has been added - specify the level of messages to be displayed in the log. Levels:
0: warn, (warning)
1: info,
2: log,
3: error.
Some logLevel variable will indicate below which level of the message not to display.
 (function(w, logLevel, wcA){ var lvl =0 ,$x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el}; for(var i in wcA) //[i]      w[i] = (function(lvl, wcAI, i){ return function(a){ a = a!==undefined|| arguments.length ? a :''; if(w.console && logLevel <= lvl) Function.prototype.apply.call(w.console[i], w.console, this instanceof String //w.console[i].apply(console, this instanceof String //--for without IE ? [wcAI + this +"'"].concat([].slice.call(arguments)) : arguments); else w.console[i] = function(){}; } })(lvl++, wcA[i], {wcw:'warn', wci:'info', wcl:'log', wce:'error'}[i]); w.wcc = w.console.clear; $x(String.prototype, {wcw: w.wcw, wci: w.wci, wcl: w.wcl, wce: w.wce, wcc: w.wcc }); })(window, /*logLevel*/ 0, {wcw:"'-w-", wci:'--', wcl:"'==", wce:"'=E="}); 


2.4. Four levels of messages in the logs or in the block on the screen


In case of impossibility to use the console, the code will have to be almost doubled to form the output of the logs into a visible block on the screen. As an additional function, the ability to restart the logger is added anywhere in the program, changing both the logging details by choosing logLevel, and output to the screen or to the console. Logging is disabled by setting logLevel = 4 on restart.
(For this to run in IE8-, we need auxiliary definitions :)
Hidden text
 if(!Array.indexOf) //old browser support Array.prototype.indexOf = function(obj){ for(var i =0, iL = this.length; i < iL; i++) if(this[i] == obj) return i; return -1; }; if(!document.getElementsByClassName) document.getElementsByClassName = function(className){ if(!className) return []; var e = document.getElementsByTagName('*') ,list = []; for(var i =0, iL = e.length; i < iL; i++){ var clss = e[i].className.split(' '); if(clss.indexOf(className) >-1) list.push(e[i]); } return list; }; 

$ e () is a way to generate blocks:
Hidden text
 var $e = function(g){//g={el,cl,ht,cs,at,on,apT} if(!g.el && g.el !==undefined && g.el !='') return g.el; g.el = g.el ||'DIV'; var o = g.el = typeof g.el =='string'? document.createElement(g.el) : g.el; if(o){ if(g.cl) o.className = g.cl; if(g.cs){ if(!IE) $x(o.style, g.cs); else{ var s =''; for(i in g.cs) s += toCsKey(i) +':'+ g.cs[i] +';'; o.style.cssText = s; }} if(g.ht || g.at){ var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;} if(at) for(var i in at){ if(i=='innerHTML') o[i] = at[i]; else o.setAttribute(i, at[i]);} g.apT && g.apT.appendChild(o); //  ,   return o; } 

 var logOnScreen =1 ,logLevel =0 //0..4 ,consoleOrig ,loadLogger = function(onScreen, logLevel){ logLevel = logLevel !==undefined ? logLevel : 3; var w = window, wcA ={wcw:"'-w-", wci:'--', wcl:"'==", wce:"'=E="} ,cons = w.document.getElementsByClassName('console')[0]; if(onScreen){ //       if(!cons) cons = $e({cl:'console',cs:{position:'fixed',width:'600px',minHeight:'150px',maxHeight:'800px',overflow:'auto',overflowX:'hidden',overflowY:'auto',top:'-2px',left:'300px',zIndex:99999,fontSize:'13px',fontFamily:'Arial',backgroundColor:'#a5c6ee',opacity:0.65, filter:'progid:DXImageTransform.Microsoft.Alpha(opacity=65)'}, apT: w.document.body }); cons && (cons.style.display ='block'); var consA = {warn:'w', info:'i', log:'', error:'E'}; if(!w.console) w.console ={}; consoleOrig = w.console; w.console ={}; lvl =0; for(var i in consA){ w.console[i] = (function(lvl, consAI, conCA){return function(aa){ if(cons && logLevel <= lvl){ cons.innerHTML +=['<i class=cons'+ conCA +'>'+ (this instanceof String ?"'=="+ this +"'": consAI) +'</i>'].concat([].slice.call(arguments)) .join('<i class=consDelim>/ </i>') +'<br>'; cons.scrollTop = Math.max(0, cons.scrollHeight); } } })(lvl++, consA[i], i.charAt(0).toUpperCase() + i.substr(1) ); } w.console.clear = function(a){if(cons) cons.innerHTML ='';} }else cons && (cons.style.display ='none'); lvl =0; for(var i in wcA) //[i]      w[i] = (function(lvl, wcAI, i){ return function(a){ a = a!==undefined|| arguments.length ? a :''; if(w.console && logLevel <= lvl) Function.prototype.apply.call(w.console[i], w.console, this instanceof String //w.console[i].apply(console, this instanceof String //--for without IE ? [wcAI + this +"'"].concat([].slice.call(arguments)) : arguments); else w.console[i] = function(){}; } })(lvl++, wcA[i], {wcw:'warn', wci:'info', wcl:'log', wce:'error'}[i]); w.wcc = w.console.clear; $x(String.prototype, {wcw: w.wcw, wci: w.wci, wcl: w.wcl, wce: w.wce, wcc: w.wcc }); }; 


This logger is started after the DOM is loaded, because a div can be used to display the logs.
 if(window.addEventListener) this.addEventListener('DOMContentLoaded',tst,!1); else this.attachEvent('onload',tst); var tst = function(){ loadLogger(logOnScreen, logLevel); wcl('tst1'); wcl(); 'tst2'.wcl(); 'tst3'.wcl({t: 23, o:{s: true}}); 'tst-wcw'.wcw(120) 'tst-wci'.wci(121) 'tst-wcl'.wcl(122) 'tst-wce'.wce(123) }; 
If the height of the text exceeds the maximum height of the block, the scrolling by the string "cons.scrollTop = Math.max (0, cons.scrollHeight);" will act.

3. Timing Design


There is reason not to adhere to the format of the β€œtime *” logs, because they are not informative in the original format. Only one argument is used, and the output string contains only the counted time. So that the string is not empty, it is better to fill it with one of the log formats, for example, wci (), putting in it the calculated interval and other values ​​from the remaining arguments. True, for this you need to duplicate the calculation mechanism, making it at the same time for IE. This will also give the opportunity to display the values ​​in div.

Let's make it easier to start - let the timers work only for the console. But we have an redundant form: the context method and the normal function. Let 'x'.wct () be the start of the timer, and wct (' x ') its ending. If there are more than two arguments, 2 lines are output: the usual log, and then the timing.

There is no timeStamp () space in this system, although it would be possible to come up with the wcts () function for them, also with any number of arguments. But it is better to stick to minimalism.
(we will shuffle the code similar to the previous one)
 var logOnScreen =0 ,logLevel =1 //0..4 ,logTime =1 ,consoleOrig ,loadLogger = function(onScreen, logLevel){ logLevel = logLevel !==undefined ? logLevel : 3; var w = window, wcA ={wcw:"'-w-", wci:'--', wcl:"'==", wce:"'=E="} ,cons = w.document.getElementsByClassName('console')[0]; if(onScreen){ //       if(!cons) cons = $e({cl:'console',cs:{position:'fixed',width:'600px',minHeight:'150px',maxHeight:'800px',overflow:'auto',overflowX:'hidden',overflowY:'auto',top:'-2px',left:'300px',zIndex:99999,fontSize:'13px',fontFamily:'Arial',backgroundColor:'#a5c6ee',opacity:0.65, filter:'progid:DXImageTransform.Microsoft.Alpha(opacity=65)'}, apT: w.document.body }); cons && (cons.style.display ='block'); var consA = {warn:'w', info:'i', log:'', error:'E'}; if(!w.console) w.console ={}; consoleOrig = w.console; w.console ={}; lvl =0; for(var i in consA){ w.console[i] = (function(lvl, consAI, conCA){return function(aa){ if(cons && logLevel <= lvl){ cons.innerHTML +=['<i class=cons'+ conCA +'>'+ (this instanceof String ?"'=="+ this +"'": consAI) +'</i>'].concat([].slice.call(arguments)) .join('<i class=consDelim>/ </i>') +'<br>'; cons.scrollTop = Math.max(0, cons.scrollHeight); } } })(lvl++, consA[i], i.charAt(0).toUpperCase() + i.substr(1) ); } w.console.clear = function(){if(cons) cons.innerHTML ='';}; }else cons && (cons.style.display ='none'); lvl =0; for(var i in wcA) //[i]      w[i] = (function(lvl, wcAI, i){ return function(a){ a = a!==undefined|| arguments.length ? a :''; if(w.console && logLevel <= lvl) Function.prototype.apply.call(w.console[i], w.console, this instanceof String //w.console[i].apply(console, this instanceof String //--for without IE ? [wcAI + this +"'"].concat([].slice.call(arguments)) : arguments); else w.console[i] = function(){}; } })(lvl++, wcA[i], {wcw:'warn', wci:'info', wcl:'log', wce:'error'}[i]); w.wcc = w.console.clear; w.wct = !document.all && logTime ? (function(lvl, wcAI, i){ return function(a){ arguments.length ? (arguments.length !=1 || this != w ? this.wcl.apply(this,arguments) :0 ,console.timeEnd.call(console, this != w ? this : a) ): console.time.call(console,this); } })() : function(){}; $x(String.prototype, {wcw: w.wcw, wci: w.wci, wcl: w.wcl, wce: w.wce, wcc: w.wcc, wct: w.wct }); }; 

You can check it like this:
 var tst = function(){ loadLogger(logOnScreen, logLevel); 'x'.wct() wcl('tst1'); wcl(); 'tst2'.wcl(); 'y'.wct() 'tst3'.wcl({t: 23, o:{s: true}}); wct('x') wct('y',' ') }; 

Looks like:

Fiddle: jsfiddle.net/spmbt/Wgah8

Source: https://habr.com/ru/post/198372/


All Articles