Bizarre console.log behaviour (console.log syndrome)
Hello gud people! Today I am going to share one bizarre experience that happened to me recently. It was when I used console.log for logging my objects in my browser. The error cause me a day of debugging and reviewing my code. Finally when I found the root cause fo the problem, I named it as “console.log syndrome”
Let’s get started..
Before we begin I would like you guys to have a look at the following code :
function init() {
let results = [
{ name: 'a1', count: 2 },
{ name: 'a1', count: 3 },
{ name: 'a1', count: 4 },
{ name: 'a2', count: 5 },
{ name: 'a2', count: 6 },
];
/*
This holds the result name as key
*/
let map = {};
/*
Loop throught the result
*/
results.forEach(result => {
let res = null
if (typeof map[result.name] === 'undefined') {
res = { name: result.name, count: 0 }
map[result.name] = res
console.log(`${res.name} not found new count : ${res.count}`)
console.log({ res })
} else {
res = map[result.name]
console.log(`${res.name} found count : ${res.count}`)
console.log({ res })
}
addCount(result, res)
}); // foreach ends
console.log({ map })
function addCount(result, res) {
res.count += result.count
}
}
init();
We can see from the above code that we have a result array and each result array has element with name and count filed. The only purpose of this program is to print the sum of the count of same name. So the sum of a1 should be 9 and sum of a2 should be 11. So for this purpose we will loop through the results array and insert final sum in the map object. You can just copy and paste the code in jsfiddle and see the result. Here’s my output
a1 not found new count : 0
{res: {…}}res: {name: "a1", count: 9}count: 9name: "a1"__proto__: Object__proto__: Object
a1 found count : 2
{res: {…}}res: {name: "a1", count: 9}__proto__: Object
a1 found count : 5
{res: {…}}res: {name: "a1", count: 9}__proto__: Object
a2 not found new count : 0
{res: {…}}res: {name: "a2", count: 11}__proto__: Object
a2 found count : 5
{res: {…}}res: {name: "a2", count: 11}__proto__: Object
{map: {…}}map: a1: {name: "a1", count: 9}a2: {name: "a2", count: 11}__proto__: Object__proto__: Object
We can see that the count of same res object is printed different when printed as string and when printed as object. Its worthwhile to note that when printed as object it printed the final result in each iteration. Now I would like you to add a breakpoint in addCount(result, res)
. You can notice that now after adding the breakpoint the output of res.count will be same as the output got by passing string in console.log. This is what I call “console.log syndrome”
So why is this happening ?
Well from this stackoverflow answer. We can know that console.log is not standardized and what my post want to convey may not be correct at the time you are reading. But while looking deep into the cause of the problem I have found that when we pass object in console.log function these objects gets queued until the console is ready so a memory representation is referenced. In simple, when we pass some object to console.log statement, the object needs to be stored somewhere and that specific location - where its stored, is taken as reference. In our case the same res object was taken as reference. We can see from the code above that we have added the count element is res object in addCount(result, res)
function. So the this piece of code res.count += result.count
caused our count to be increased.
How to avoid console.log() error ?
This is what I think will remedy the console.log syndrome hazards
- My main suggestion is to avoid using console.log(). Now a days we can find handy debugger tools in browser themselves.
- If you are from node.js then we can use tools like node inspector to debug the application. Here is a very good article on how to stop using console.log().
- Pass string in console.log. If we pass a string in console.log statement, a new reference to that string is created and will prevent the error. In the above example, if you json stringify the res object and print you will not see this error.