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.