8

I'm curious about the way Node.js prints objects through console.log(object).

I have the following code (from Learning Javascript Design Patterns book) under a file constructor.js

var defineProp = function(obj, key, value){
    var config = {
        value: value, 
        writable: true,
        configurable: true
    };
    Object.defineProperty(obj, key, config ); 
}

var person = Object.create(Object.prototype);


defineProp(person, "car", "Delorean"); 
defineProp(person, "dateOfBirth", "1981"); 
defineProp(person, "hasBeard", false); 

console.log(person); //This prints {} in Node.js

Running with that code with >node constructor.js prints an empty object. Chrome however, prints what I would expect if I run the code inside an HTML file.

console.log(person); //Chrome prints Object {car: "Delorean", dateOfBirth: "1981", hasBeard: false} 

Note: I can still print the attributes (such as console.log(person.car)) under Node, just not the object itself (such as console.log(person))

Why is this? Do Chrome and Node use separate prototypes for the console object, even though they share the same javascript engine?

SamuelN
  • 1,341
  • 1
  • 10
  • 19
  • 4
    Not sure why they're different, but if you add `enumerable: true` to the `config` object the properties will print in node.js. – JohnnyHK Oct 05 '15 at 04:32
  • Possible duplicate of [View methods of Node.js String.prototype?](http://stackoverflow.com/questions/12536510/view-methods-of-node-js-string-prototype) – Qantas 94 Heavy Oct 05 '15 at 04:32
  • 2
    By default, properties created with `defineProperty()` are not enumerable. So, perhaps node.js is only showing you enumerable properties and Chrome shows non-enumerable properties. `console.log()` is not a something specified in a standard and it is a host object, not official part of the Javascript language so different environments may have different behaviors. – jfriend00 Oct 05 '15 at 04:35
  • 1
    The console.log in node is very different to the one in Chrome. First, node prints to stdout so its console.log had to be re-written to support streams. Which means from the very beginning node wasn't using the same console.log as Chrome. Second, from version 0.6 onward node's console.log is synchronous (vs Chrome's asynchronous) because people expected to see the last console.log they printed before their servers crash. Not being synchronous made it very difficult to debug crashing servers because the cause of the crash wouldn't be logged before node exits – slebetman Oct 05 '15 at 04:41
  • @slebetman node's `console.log()` is only synchronous when stdout is redirected to a file. Otherwise it is always asynchronous on all platforms. There are already several issues on node's github issue tracker about that. – mscdex Oct 05 '15 at 04:59
  • @mscdex: Last time I tried (admittedly that was 3 months ago) console.log on node was synchronous when printing to the terminal – slebetman Oct 05 '15 at 05:03
  • @slebetman For older node versions it depended on the platform and node version. – mscdex Oct 05 '15 at 05:03
  • @mscdex: It was 0.14.something.. on Linux before the merge with io.js. I wouldn't say that's an "old" version. It's still being used in production in places not yet willing to upgrade to io.js. I was benchmarking go/nodejs/C(gcc/clang) and couldn't make node do async i/o to terminal – slebetman Oct 05 '15 at 05:08
  • FWIW there never was a node v0.14. node pre-merge was v0.12.x and post-merge started at v4.0.0. io.js started at v1.0.0. I believe node v0.12.x and earlier had platform-dependent behavior for stdio. – mscdex Oct 05 '15 at 05:15

1 Answers1

6

console.log() in node utilizes util.inspect(), which uses Object.keys() on objects, which returns only own enumerable properties. Also, by default, Object.defineProperty() sets enumerable: false if you do not explicitly set it to true.

mscdex
  • 104,356
  • 15
  • 192
  • 153