I frequently have a need to print three.js objects to the console during debugging sessions. Unfortunately, the current experience leaves much to be desired.
The simplest method is to simply print the object directly:
const box = new Box2(); console.log(box);
However, this has two problems: first, the console won’t display the actual coordinates, but instead will display an “Object” which you must manually expand by clicking. This is inconvenient if you have a large amount of debugging output and you are looking for anomalies.
The second problem is that when you print an object to the console, what the console displays is the value of the object right now - not what the value was at the time it was printed out. Recall that three.js recommended practices includes re-using vectors, boxes, planes and other objects rather than creating them new each time. This means that what is printed on the console may not be the value you were looking for.
A different approach is to manually destructure the object:
const box = new Box2(); console.log(box.min.x, box.min.y, box.max.x, box.min.y);
This has the advantage of providing the correct data, but it’s cumbersome to have to do this every time you want to log a three.js object.
What would be ideal is if all three.js objects had some kind of “toString()” method:
const box = new Box2(); console.log(box.toString());
Unfortunately, that does not exist. There are a couple of other things one could try:
const box = new Box2(); console.log(JSON.stringify(box));
The problem here is that (1) the extra quotes that JSON adds makes the output more cluttered, and (2) if the object contains any internal fields that are not part of its official API those will get included as well. As a general rule, I don’t like calling
JSON.stringify() on class instances that are not vanilla objects.
You could also write a helper function for debugging:
const box = new Box2(); console.log(boxToString(box));
…however, you would eventually end up needing to write such a helper for every three.js type, or at least the most common ones. This seems like the kind of thing that individual three.js users should not have to reinvent themselves. And having to import the helper is not as convenient as having it be a method on the object, especially given that you’ll want to remove the import when you are done debugging.
The other approach, I suppose, is to make a swiss-army-knife stringifier that knows about many different kinds of three.js objects:
const box = new Box2(); console.log(formatThree(box)); // This will type-test that it's a box and format appropriately
This at least has the advantage that it’s only one import, but it still seems like the kind of thing that ought to be generally available rather than having each developer re-implement it.
Any other approaches I missed?