admin管理员组文章数量:1336346
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="style.css">
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
for (const div of document.querySelectorAll("div")) {
console.log(div);
}
</script>
</body>
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="style.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:
and sometimes as if I used console.dir()
instead of console.log()
:
Rarely, I get a mix:
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 style.css
is currently pletely 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?
Share Improve this question edited Aug 2, 2023 at 9:58 Michael Haddad asked Feb 8, 2022 at 12:37 Michael HaddadMichael Haddad 4,4658 gold badges48 silver badges89 bronze badges 8- 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 Commented Feb 8, 2022 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 Commented Feb 8, 2022 at 12:44
-
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 printingdocument.readyState
with each div also showed no correlation (I tried these tests independently and together). – Corey Ogburn Commented Feb 8, 2022 at 16:44 -
4
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 Commented Feb 8, 2022 at 16:53 - 2 @CoreyOgburn - I think your investigation deserves to be in an answer. – Michael Haddad Commented Feb 8, 2022 at 16:59
2 Answers
Reset to default 4It is not a bug nor a feature but more of a trade-off. I gave an answer to a similar question about "how to", thus is was short. Here is about "why", so it needs more "academic" explanation.
It is related to how the Chromium DevTools logging work in union with the Blink engine, here is a simplified scenario for a DOM node:
console.log(document.querySelector('div'));
Blink V8::console.log
-> IPC ->
Chromium Process
-> IPC ->
DevTools front-end fork
That is, V8 executes console.log
method implemented by Blink, which triggers a message for DevTools
. That message is handled by IPC
which in Blink is mainly asynchronous.
Once DevTools Console
receives a Node
object it must inspect the DOM Renderer
to sync with it's actual render tree, so that when hovering on the node in the console the Renderer
would highlight the node in browser page, so there it is:
DevTools inspect
-> IPC ->
Chromium Process
-> IPC ->
Blink DOM Render
Here is the problem, since the DOM Renderer
is busy with synchronous style loading, in this specific case the render-blocking resource is link
element, so it fails to respond timely and instead of render tree representation the console fallback to object representation of it, doing so instead of just showing a string representation gives the possibility to inspect that node anyway, a sane trade-off, albeit without the modity of seeing it's mirror reference.
Additionally, other peculiarities of DevTools Console
may be noted:
- It does not really matter which
console
method was called, as they are mainly aliases for log level definition and not for special handling of object inspection, soconsole.error
behaves the same for that reason. DevTools inspect
is issued only ifConsole
tab is active or bees active. So while it may show a object representation of node when performing the tests with an activeConsole
tab, when performing them while being on another tab, let's sayPerformance
, then switching toConsole
we can see those nodes appearing one by one as render tree, since by that time theDOM Render
will be accessible.- A mon myth about logged objects is that they mutates in the console when they are mutated by the JS runtime. Well, they are not. The
Console
creates a static "fingerprint" of object only for current level tree. It then creates a deeper tree on demand, when manually unfolding it, so it just uses for that new tree the current values which may give false impressions that it mutates the log.
I modified a bit the initial example, to be more like a "real" application, also to reveal the above behavior. Additionally, for more stress on render engine, it may be played with a x4
or x6
CPU throttling in the DevTools Performance
tab.
<head>
<script>
document.addEventListener('DOMContentLoaded', () =>
console.log('DOMContentLoaded'));
</script>
<link rel="stylesheet" href="css.css">
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<script crossorigin src="https://unpkg./react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg./react-dom@18/umd/react-dom.development.js"></script>
<script>
for (const div of document.querySelectorAll("div")) {
console.log(div);
}
let i = 1000, div, divs = [], ids = [];
while (i--) {
div = document.createElement('div');
div.textContent = new Date().toISOString();
document.body.appendChild(div);
if (!(i % 100)) {
const id = {id: i};
ids.push(id);
divs.push(div);
console.log(id, {div}, div);
}
}
setTimeout(() => {
for (const id of ids)
id.id = Math.random();
for (const div of divs) {
div.style.color = 'red';
const child = document.createElement('div');
child.textContent = 'OK';
div.appendChild(child);
}
}, 1000);
</script>
</body>
NOTE: The console.log
results must be checked in the DevTools
not in the playground here, as it just parses the arguments of console.log
with it's own parser and has nothing to do with real console.log
behavior.
I've read the ments 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 remended way to log objects to console).
the logic behind this remendation 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.
本文标签: javascriptGoogle Chrome39s consolelog() prints DOM nodes inconsistentlyStack Overflow
版权声明:本文标题:javascript - Google Chrome's console.log() prints DOM nodes inconsistently - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742270447a2444203.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论