Your console.log Is Lying to You: debugging traps and tricks
Why console.log() Can Be Misleading
console.log() is the most common debugging tool in JavaScript, but it can actively deceive you. The browser DevTools do not always show you what you expect.
Live Object References
When you log an object, DevTools stores a live reference, not a snapshot. If you expand the object in the console later, you see its current state, not the state at the moment you logged it.
let data = { count: 0 };
console.log(data); // Shows { count: 1 } when expanded later
data.count = 1;
To capture a snapshot, log a copy:
console.log(JSON.parse(JSON.stringify(data)));
// or
console.log({ ...data });
Promises That Look Different When Expanded
A logged Promise may appear as Promise { <pending> } in the console. When you expand it later, after the promise resolves, it shows the resolved value. This can make you think the promise resolved synchronously when it did not.
console.log(fetch('/api')); // Shows pending, then resolved when expanded
Logs Changing Timing-Sensitive Behavior
Adding console.log() can alter the timing of your code. The logging operation itself takes time, which can shift race conditions, animation frames, or network callbacks.
// Without log: works
// With log: breaks due to timing shift
requestAnimationFrame(() => {
console.log('frame');
// timing-sensitive logic here
});
Stale React State After Updates
In React, console.log(state) inside a component often shows the previous state, not the current one. This happens because closures capture the state at render time, and the log runs before the next render.
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log(count); // Shows old value
setCount(count + 1);
};
}
To see the updated state, log inside a useEffect:
useEffect(() => {
console.log(count); // Shows new value after render
}, [count]);
Source Maps Pointing at Surprising Line Numbers
When using transpilers (Babel, TypeScript) or bundlers (Webpack, Vite), source maps map compiled code back to original source. However, line numbers can be off by one or more due to how source maps handle whitespace, comments, or multiple statements on one line.
// Original TypeScript
const x: number = 5; // Source map may point to wrong line
Check the actual compiled output in the Sources panel, not just the source-mapped view.
Comments
No comments yet. Start the discussion.