9

Not a duplicate of Google Chrome console.log() inconsistency with objects and arrays, since this question is not about objects and arrays.


Here is a simple HTML page:

<head>
  <link rel="stylesheet" href="css.css">
</head>

<body>
  <div></div>
  <div></div>
  <div></div>
  <div></div>

  <script>
    for (const div of document.querySelectorAll("div")) {
      console.log(div);
    }
  </script>
</body>

Sometimes the results are shown as they presumably should:

enter image description here

and sometimes as if I used console.dir() instead of console.log():

enter image description here

Rarely, I get a mix:

enter image description here

When I tried to create the minimal, reproducible example shown above, I removed the <link>, as it didn't seem to be related to the problem. However, after removing it, the inconsistency disappeared, so I restored it and tried to minimize the CSS itself, to the point where css.css is currently completely empty. So somehow the mere presence of the <link> tag seems to be at least related to the problem.

Is there a reason for this behavior, or is it a bug?

isherwood
  • 52,576
  • 15
  • 105
  • 143
Michael Haddad
  • 3,609
  • 7
  • 37
  • 70
  • 7
    In my experience this can depend on at which point you open the console, i.e. if I open it after the content has already been logged it isn't formatted as nicely – Marces Engel Feb 08 '22 at 12:39
  • 1
    In my experience this mostly happens when the browser is still parsing the DOM. Hence the issue can shows up when (for example) you add a stylesheet. – Reyno Feb 08 '22 at 12:44
  • @Reyno Well, since the `div`s *are* printed, doesn't it mean that the DOM (or at least the relevant part of it) is already loaded when the script is executed? – Michael Haddad Feb 08 '22 at 12:48
  • 2
    I can duplicate OPs results. @MarcesEngel, I had the console open during multiple refreshes and it doesn't seem related to when you open the console. @Reyno, I thought the same thing, but wrapping the provided JS in a document event listener for `DOMContentLoaded` and printing `document.readyState` with each div also showed no correlation (I tried these tests independently and together). – Corey Ogburn Feb 08 '22 at 16:44
  • 3
    Notice that during the rare instance you get a mix of outputs, you get collapsable objects before you get the HTML dump. I think what's happening is that rendering and the javascript engine are in different threads and at some point they sync up and settle. BEFORE they settle, javascript objects are printed. You can uncollapse each div and see all the javascript visible properties. AFTER they settle, the raw HTML is printed. If you use a timeout and an event listener to fire the code a small amount of time after the `DOMContentLoaded` event fires, then it ALWAYS prints the HTML. – Corey Ogburn Feb 08 '22 at 16:53
  • 1
    @CoreyOgburn - I think your investigation deserves to be in an answer. – Michael Haddad Feb 08 '22 at 16:59
  • 1
    I was writing up my answer just now and I was trying to recreate my results but I ended up with a split output situation that output HTML style divs before it output the JSON style divs. That blows my theory out of the water because it should only work the other way around. I thought the renderer was updating the JS engine with DOM hints not taking them away. – Corey Ogburn Feb 09 '22 at 02:42

1 Answers1

2

I've read the comments by @Corey, and yet I want to point you to the docs which contradicts what Corey said.

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 open the console.

now as per the difference between console.log() and console.dir(). besides the difference in the way they print the DOM element, another differentiator is as follows:

console.log gives special treatment to DOM elements, whereas console.dir does not. This is often useful when trying to see the full representation of the DOM JS object.

possible solution / another test case is, by yet again, referencing the docs, to log DOM elements is not console.log(obj), but actually console.log(JSON.parse(JSON.stringify(obj))) (and this actually the recommended way to log objects to console).

the logic behind this recommendation is that in this way you can be sure you are seeing the value of obj at the moment you log it. Otherwise, many browsers provide a live view that constantly updates as values change. This may not be what you want.

Guy Nachshon
  • 2,075
  • 2
  • 15
  • Thank you. As far as I can understand, though your answer does suggest an alternative way of printing DOM elements, it does not address the inconsistent results when using `console.log()`. Is it a bug or a feature? If it's supposed to happen, why and when? Thanks again. – Michael Haddad Apr 28 '22 at 20:34