How to prettify output of objects in the console, when using get/set, like browsers do?

# #!/JoePea (5 years ago)

Here's some nice output in the console in Chrome, for DOMPoint and DOMPointReadOnly classes:

const point = new DOMPoint(1,2,3,4)
console.log(point)

output:

> DOMPoint {x: 1, y: 2, z: 3, w: 4}

(codepen example, open the devtools console then re-run the example to see the "nice" output)

However if I use the my polyfill here, then the output is not as helpful:

const point = new DOMPoint(1,2,3,4) // uses polyfill
console.log(point)

output (notice, it does not show the x,y,z,w values):

> DOMPoint {}

(codepen example, open the devtools console then re-run the example to see the expected output)

When I expand the object in the console, I can see the getters, marked with (...), and I can click on them to trigger them, but the output is limited and does not show the x,y,z,w values like the native one does.

Is it possible to make the output nice with the polyfill? Or does the engine have internal mechanisms that we don't get to use in plain JavaScript?

# Jordan Harband (5 years ago)

console isn't part of the language; node and browsers have their own implementations (which is likely covered by an HTML spec), so you'd want to look into it there.

node's util.inspect, for example, provides a util.inspect.custom symbol that's invoked to get a custom string version of the object: nodejs.org/api/util.html#util_util_inspect_custom

# dante federici (5 years ago)

So, it actually all works as you'd expect when using properties on the class itself:

In that polyfilll, it actually is making x, y, z, and w private fields: trusktr/geometry-interfaces/blob/41d8cca9c0b4e4ab7afbb9a3a1d02ca94d048f3f/src/DOMPoint.js#L2

const _ = o => {
    if (!privatesMap) {
        privatesMap = new WeakMap
        let privates = {}
        privatesMap.set(o, privates)
        return privates
    }
    else {
        let privates = privatesMap.get(o)

        if (privates === undefined) {
            privates = {}
            privatesMap.set(o, privates)
        }

        return privates
    }

So, the new instances never have a visible property for the console to display. Compare to:

class Test {
    constructor(x) { this._x = x }
    get x(){ return this._x; }
    set x(v){ this._x = v; return v; }
}
console.log(new Test(123));
> Test { x: 123 }