Search code examples
javascriptnode.jsjsonstringify

Why does Json's Stringify output print differently from console.log output?


For the below code:

const testStringify = () => {
        try{
            console.log('Inside testStringify');
            const a = "";
            a.b.c;
        } catch(err) {
            console.log('Inside catch of testStringify');
            console.log(`Error: ${JSON.stringify(err)}`);
            console.log(err);
        }
    }
    
    testStringify();

The output is:

Inside testStringify
Inside catch of testStringify
Error: {}
TypeError: Cannot read property 'c' of undefined
    at testStringify
    at Object.<anonymous>
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3

Why does Json.stringify(err) (Error: {}) not print output in the same way or in some meaningful way as console.log(err)?


Solution

  • JSON.stringify iterates only over own and enumerable properties.

    const obj = Object.create({ onProto: 'onProto' });
    Object.defineProperty(obj, 'notEnumerable', { value: 'notEnumerable' });
    obj.ownAndEnumerable = 'ownAndEnumerable';
    console.log(JSON.stringify(obj)); 

    In some browsers, the .message property of Error objects is not an own enumerable property, so it doesn't get iterated over.

    For example, in Chrome, the property is own but not enumerable:

    const e = new Error('msg');
    console.log(Object.getOwnPropertyDescriptor(e, 'message'));

    console.log(err), on the other hand, will display the full object in the interactive console.