I found out how to do it in Chrome DevTools (still don't have a solution for VSCode):

For this to work we need to enable custom formatters in dev tools:
- Open dev tools
- Click on the hamburger menu (the 3 vertical dots) on the top right
- Click on "settings"
- Under "Console", make sure "Enable custom formatters" is checked.
With this done you can create a custom formatter in the code and then assign it to window["devtoolsFormatters"]
.
The full code for my example is here:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
toString() {
return `${this.firstName} ${this.lastName}`;
}
}
Formatter = function (simpleFormatter) {
this._simpleFormatter = simpleFormatter;
}
Formatter.prototype = {
header: function (object) {
if ((object instanceof Node))
return null;
var header = new JsonMLElement("span");
let title = this._simpleFormatter.description(object);
if (typeof object.toString !== "undefined") {
title = `${object.toString()} [${this._simpleFormatter.description(object)}]`;
}
header.createTextChild(title);
return header.toJsonML();
},
hasBody: function (object) {
if (object instanceof Array)
return false;
return this._simpleFormatter.hasChildren(object);
},
body: function (object) {
var body = new JsonMLElement("ol");
body.setStyle("list-style-type:none; padding-left: 0px; margin-top: 0px; margin-bottom: 0px; margin-left: 12px");
var children = this._simpleFormatter.children(object);
for (var i = 0; i < children.length; ++i) {
var child = children[i];
var li = body.createChild("li");
var objectTag;
if (typeof child.value === "object")
objectTag = li.createObjectTag(child.value);
else
objectTag = li.createChild("span");
var nameSpan = objectTag.createChild("span");
nameSpan.createTextChild(child.key + ": ");
nameSpan.setStyle("color: rgb(136, 19, 145);");
if (child.value instanceof Node) {
var node = child.value;
objectTag.createTextChild(node.nodeName.toLowerCase());
if (node.id)
objectTag.createTextChild("#" + node.id)
else
objectTag.createTextChild("." + node.className)
}
if (typeof child.value !== "object")
objectTag.createTextChild("" + child.value);
}
return body.toJsonML();
},
_arrayFormatter: function (array) {
var j = new JsonMLElement();
j.createTextChild("[");
for (var i = 0; i < array.length; ++i) {
if (i != 0)
j.createTextChild(", ")
j.createObjectTag(array[i]);
}
j.createTextChild("]");
return j;
}
}
JsonMLElement = function (tagName) {
this._attributes = {};
this._jsonML = [tagName, this._attributes];
}
JsonMLElement.prototype = {
createChild: function (tagName) {
var c = new JsonMLElement(tagName);
this._jsonML.push(c.toJsonML());
return c;
},
createObjectTag: function (object) {
var tag = this.createChild("object");
tag.addAttribute("object", object);
return tag;
},
setStyle: function (style) {
this._attributes["style"] = style;
},
addAttribute: function (key, value) {
this._attributes[key] = value;
},
createTextChild: function (text) {
this._jsonML.push(text + "");
},
toJsonML: function () {
return this._jsonML;
}
}
function SimpleFormatter() {
}
SimpleFormatter.prototype = {
description: function (object) {
if ((typeof object === "object") && object)
return object.constructor.name;
return object;
},
hasChildren: function (object) {
return (typeof object === "object");
},
children: function (object) {
var result = [];
for (var key in object)
result.push({ key: key, value: object[key] });
return result;
}
}
window["devtoolsFormatters"] = [new Formatter(new SimpleFormatter())];
const p = new Person("Luke", "Skywalker")
console.log(p)
More details can be found in this link (my code is just a slightly modified version of one of the examples posted in that article).