2

I'm trying to understand why the following code behaves as it does. Specifically, why does the first console.log(...) expression output the full-and-final version of someObject? I realize it has something to do with hoisting (maybe?) or some other concept I don't fully grasp. Just searching this on the web was challenging, as I don't have the lexicon to properly search what I want to know.

var someObject = {};
                              // OUTPUT:
console.log(someObject);      // {prop: {key: "differentValue"}} <-- WHY!?
console.log(someObject.prop); //  undefined

someObject.prop = {key:"value"};

console.log(someObject);      // {prop: {key: "differentValue"}} <-- WHY!?
console.log(someObject.prop); // {key: "value"}

someObject.prop = {key:"differentValue"};

console.log(someObject);      // {prop: {key: "differentValue"}}
console.log(someObject.prop); // {key: "differentValue"}

I discovered this while coding something for myself wherein I wanted to see the state of an object at each iteration through a for-loop. I was surprised to see the object output to the console was the same at each turn; that state being the end-state of the object after the whole loop had executed.

What's even more confusing to me, and the part I really would like to understand, is why the reading of the properties of the object do seem to work as one (or at least I) would expect, while at the same moment, the whole object itself appears to have different values.

I thought maybe this question or this question might've helped explain, but I think they're not quite related.

PattMauler
  • 400
  • 4
  • 22

1 Answers1

4

From MDN console.log documentation:

https://developer.mozilla.org/en-US/docs/Web/API/Console/log#Parameters

Please be warned that if you log objects in the latest versions of Chrome and Firefox what you get logged on the console is a reference to the object, which is not necessarily the 'value' of the object at the moment in time you call console.log(), but it is the value of the object at the moment you click it open.

When you log the property, you see the value of the property at that time. When you log the object itself, you will see the latest version of said object.

If you want to log the object at the time, use console.log(JSON.parse(JSON.stringify(obj))).

Alberto Rivera
  • 3,652
  • 3
  • 19
  • 33
  • as a potential solution you could suggest creating a new version of the object too, but using `console.log(Object.assign({}, someObject))`. Useful if your `JSON.strinigify` option is outputting too much text to make it visibly easy to traverse – haxxxton Jan 02 '18 at 02:31
  • 3
    If you use the `Object.assign` workaround, be aware that, since the copy is shallow, changing a nested property will show the wrong output. – Alberto Rivera Jan 02 '18 at 02:34
  • Good point @alberto-rivera, your parse'd stringified option would be more appropriate then – haxxxton Jan 02 '18 at 02:36
  • 1
    Assuming the object is valid JSON. – Jared Smith Jan 02 '18 at 02:37
  • @JaredSmith that's a good point. The object must contain no circular structures, and have a valid JSON representation. – Alberto Rivera Jan 02 '18 at 02:40
  • So, this behavior is simply an artifact of console.log() and not an accurate depiction of the object at that point of execution in runtime? I can trust that the values/fields/properties are the actual values? Thanks for the detailed answer! Exactly what I was looking for. – PattMauler Jan 02 '18 at 02:45
  • @PattMauler btw, another option is to use `console.table` on the object, which will give you the right info in a table form (though the output below will still be the most recent). – Alberto Rivera Jan 02 '18 at 02:50