String Representations of Javascript Objects
toString()
and Symbol.toStringTag
⌗
The default Object.prototype.toString()
function is
defined to the specification
to return [object X]
even for non-objects:
Object.prototype.toString.call(undefined) // returns "[object Undefined]"
Object.prototype.toString.call(true) // returns "[object Boolean]"
{}.toString() // returns "[object Object]"
X
is a so-called ‘string tag’ and in newer versions of Javascipt, you can set it yourself:
{[Symbol.toStringTag]:"MyObject"}.toString() // returns "[object MyObject]"
But for objects, you can also just implement the complete toString
function:
{toString: ()=> "My Cool Object!"}.toString() // returns "My Cool Object!"
However, the toString()
function is not used by console.log()
or in the Node.js or Deno REPLs.
inspect()
is the real toString()
⌗
In Node.js, objects are converted to strings using the util.inspect()
function.
In Deno, there is the equivalent Deno.inspect()
. These methods are used
both in the REPLs and when using console.log()
.
You can influence what these do by implementing a function with the symbol nodejs.util.inspect.custom
and
Deno.customInspect
respectively. If you implement both, pretty printing works in both.
Check out this example for a binary tree:
export class Tree {
constructor(value, left, right) {
this.value = value;
this.left = left;
this.right = right;
}
[Symbol.for("Deno.customInspect")]() {
return this.toString();
}
[Symbol.for("nodejs.util.inspect.custom")](){
return this.toString();
}
toString() {
const printNode = (node, prefix = '', isLeft) => {
let str = '';
if (node !== null) {
str += `${prefix}${isLeft ? '├──' : '└──'} ${node.value}\n`;
const newPrefix = `${prefix}${isLeft ? '│ ' : ' '}`;
str += printNode(node.left, newPrefix, true);
str += printNode(node.right, newPrefix, false);
}
return str;
};
return printNode(this).trim();
}
}
And here is a Deno session that uses it:
> tree
└── 52
├── 41
│ ├── 51
│ └── 44
└── 94
├── 54
└── 36
> console.log(tree);
└── 52
├── 41
│ ├── 51
│ └── 44
└── 94
├── 54
└── 36
Isn’t that beautiful? Sadly there is no way to accomplish this in browsers.