This question has already got some reviews, so I could partially improve my code: please look at my self-answer below, which also contains comments about the review.I'm frequently interested to answer SO questions regarding (JS) objects and/or arrays manipulation.When providing a snippet, and if the actual result looks somewhat complex, it's not enough to merely console.log() it, because it's rendered as a compacted (and often even reduced) single line where it's not easy to directly retrieve each piece of data.Then I was tired to have to either spend time to arrange the output a bit (but generally not completely) or let the result appear unclear, so I decided to write a helper function for that:/** * @param src: any variable of any type * @param html: output format (true|false); default = false * @param level: (internal, don't use) * * @return string: formatted output */function showObj(src, html, level) {  level |= 0;  const tabCount = 4,  edges = '{[}]';  var tab = (!!html ? '&nbsp;' : ' ').repeat(tabCount),      br = !!html ? '<br />' : '\n',      offset = tab.repeat(level);  switch (typeof src) {    case 'boolean':    case 'number': return src.valueOf();    case 'string': return '' + src.toString() + '';    case 'symbol': return src.toString();    case 'undefined': return 'undefined';    case 'function': return (src.name || 'function') + '()';    case 'object':      if (src === null) {return 'null';}      if (src === this) {return src.valueOf();}      if (!!src.jquery) {return 'jQuery ' + src.jquery + ' object';}      if (!Object.keys(src).length) {return src;}      var output = [],          isArr = Array.isArray(src);      for (let key in src) {        output.push(          br + offset + tab + (isArr ? '' : ('' + key + ': ')) +          showObj(src[key], html, level + 1)        );      }      return edges[+isArr] + output.join(', ') + br + offset + edges[+isArr + 2];    default:      return '(unexpected!) ' + typeof src;  }}/** * @param src: any variable of any type * @param html: output format (true|false); default = false * @param level: (internal, don't use) * * @return string: formatted output */function showObj(src, html, level) {  level |= 0;  const tabCount = 4,        maxString = 40,        edges = '{[}]';  var tab = (!!html ? '&nbsp;' : ' ').repeat(tabCount),      br = !!html ? '<br />' : '\n',      offset = tab.repeat(level);  switch (typeof src) {    case 'boolean':    case 'number': return src.valueOf();    case 'string': return '' + src.toString().substr(0, maxString) +      (src.length > maxString ? '...' : '') + '';    case 'symbol': return src.toString();    case 'undefined': return 'undefined';    case 'function': return (src.name || 'function') + '()';    case 'object':      if (src === null) {return 'null';}      if (src === this) {return src.valueOf();}      if (!!src.jquery) {return 'jQuery ' + src.jquery + ' object';}      if (!Object.keys(src).length) {return src;}      var output = [],          isArr = Array.isArray(src);      for (let key in src) {        output.push(          br + offset + tab + (isArr ? '' : ('' + key + ': ')) +          showObj(src[key], html, level + 1)        );      }      return edges[+isArr] + output.join(', ') + br + offset + edges[+isArr + 2];    default:      return '(unexpected!) ' + typeof src;  }}var src = {  'null': null,  'undefined': undefined,  'this': this,  'integer': 123,  'float': 12.3,  'Infinity': Infinity,  'NaN': NaN,  'Math.PI': Math.PI,  'string': 'Some short string',  'long-string': showObj.toSource(),  'bool-true': true,  'bool-false': false,  'date': new Date(),  'regexp': /.*/i,  'error': new Error('Error message'),  'symbol': Symbol('someSymbol'),  'function': function someFunc() {},  'anonymous-func': function() {},  'simple-array': [1, 2, 3],  'simple-object': {a: 'A', b: 'B', c: 'C'},  'compound-object': {    'compound-array': [      {'integer': 123, 'float': 12.3},      {'NaN': NaN, 'string': 'A string'},      {        'sub-array': [1, 2, 3],        'sub-object': {a: 'A', b: 'B', c: 'C'}      }    ]  },  'jQuery': $('body'),  'map': new Map([['key1', 'value1'], ['key2', 'value2']]),  'set': new Set(['value1', 'value2', 'value3'])};console.log(showObj(src));document.write(showObj(src, true));* {  font-family: Courier New;  font-size: 12px;}<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script>I tried to make it together:Complete, i.e. distinguishing each kind of data structure I could think to (but maybe I forgotten some cases?).Clear but concise, e.g. cutting long strings, omitting to expand this or jQuery objects, and so on.Also with a reduced code (I'm not re-writing a console :).I'm expecting comments about especially the three aspects above, as well as about anything wrong I might have done.
Helper function to format-output any type of variable
javascript;formatting;helper
Your code could do with some formatting. As it stands, it sure is short, but we have minifiers for that sort of thing. I have to spend a lot of effort to read certain parts because it is filled with clever tricks.var one = {};var two = {'one':one};one.two = two;If I now pass either of one or two into showObj, it produces an error:Uncaught RangeError: Maximum call stack size exceededWhich is worse than using the console, given that console.log(one) would have given me a nice expandable object, in chrome at least. You might want to handle circular references like this. Printing any sort of doubly linked-list will kill your showObj.