P粉9305342802023-08-28 22:01:29
This isn't really the answer to the question, but it might be handy for anyone who stumbles across this post and it's too long a comment:
window.console.logSync = (...args) => { try { args = args.map((arg) => JSON.parse(JSON.stringify(arg))); console.log(...args); } catch (error) { console.log('Error trying to console.logSync()', ...args); } };
This will create a pseudo-synchronous version of console.log
but with the same warnings mentioned in the accepted answer.
Since it appears that most browsers' console.log
these days are asynchronous in some way, you may want to use a function like this in some cases.
P粉1419251812023-08-28 15:47:19
console.log
is not standardized, so the behavior is rather undefined and can change easily between different versions of developer tools. Your book may be out of date, and my answers may soon be out of date.
For our code, it makes no difference whether console.log is asynchronous or not, it doesn't provide any kind of callbacks, etc.; and the value you pass is always referenced and evaluated when you call the function.
We don't really know what's going to happen next (well, we can, since Firebug, Chrome Devtools, and Opera Dragonfly are all open source). The console needs to store the logged values somewhere and display them on the screen. Rendering will definitely happen asynchronously (subject to rate-limited updates), as will future interactions with objects logged in the console (such as extending object properties).
So the console may clone (serialize) your logged mutable objects, or it may store references to them. The first one doesn't work with deep/large objects. Also, at least the initial render in the console might show the "current" state of the object, which is the state at the time of recording - in your example you'd see Object {}
.
However, when you expand the object to further examine its properties, the console may only store references to the object and its properties, showing them now will show its current (mutated) state. If you click on
, you should be able to see the bar
property in the example.
Here is the screenshot posted in the bug report explaining their "fix":
Therefore, some values may not be referenced until long after they are recorded, and the evaluation of these values is rather lazy ("when needed"). The most famous example of this difference is in the question Is Chrome's JavaScript console handling lazy evaluation of arrays?
The workaround is to ensure that a serialized snapshot of the object is always logged, for example by doing console.log(JSON.stringify(obj)). However, this only works for non-circular and fairly small objects. See alsoHow to change the default behavior of console.log in Safari? .
A better solution is to use breakpoints for debugging, where execution stops completely and you can inspect the current value at each point. Use logging only for serializable and immutable data.