Chrome and Safari have a pretty serious bug where console.log() does not log variables as they are at the time of calling console.log(), but rather as they are some time in the future. If you’re not aware of it, you can go insane trying to figure out where your code is going wrong, when actually console is logging values not-at-runtime.
This bug only affects (non-null) Objects and Arrays.
Logging Objects
First, let’s look at the logging of objects. When logging an object, Webkit’s console.log only prints a reference to that object in the log titled “Object”. It is not until you click on the arrow to expand it that it actually logs the data.
Consider:
1 2 3 4 5 6 | (function(){ var obj = {}; console.log(obj); obj.new_value = "hello"; console.log(obj); })(); |
Here’s how Webkit logs it:
And how FireBug does:
As you can see, Webkit’s console.log() doesn’t correctly log object values. This seems like a rather large and ridiculous oversight, especially if you consider what the point of console.log() is — to log the values of a variable.
Logging Arrays
With arrays, it’s even worse. The console dumps out the contents of the array. However, it’s not clear (or guaranteed) what version of the array is being dumped. In most cases, it will just dump the latest version of the array referenced in console.log().
Consider:
1 2 3 4 5 6 7 8 | (function(){ var arr = [1]; console.log("first: ", arr); arr.push(2); console.log("second: ", arr); arr.push(3); console.log("third: ", arr); })(); |
Here’s how it’s logged in WebKit browsers:
And here’s how any sane developer would expect it to look like, in FireBug:
Digging Deeper
With objects, the data is logged when we hit the expand arrow, but what about with arrays? If we call console.log, wait a little bit, then change the array, will it log the value when we called console.log(), or the new value?
Let’s experiment! Here’s code that sets various timeouts of 1, 2, 4, 8, … ms. When each timeout is executed, the 0th offset of the array is set to the actual amount of time elapsed, and console.log is called. If there’s a discrepancy between what we set the value to (the value at run-time), and the value logged, we’ll be able to see it. With enough delay, the two values should be equal.
Here’s some code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (function(){ var arr = []; var update_array = function(){ var time_since_start = (new Date()).getTime() - start_time; arr[0] = time_since_start; console.log("Value set to: " + time_since_start, arr); } var start_time = (new Date()).getTime(); for (var i=0; i<=10; i++){ var time = Math.pow(2, i); setTimeout(update_array, time); } })(); |
In Chrome:
In Safari:
And in FireBug:
What does this tell us? In WebKit browsers, there’s clearly a delay between when we *call* console.log() and when the array is *actually* logged. It looks on my machine the delay is not constant, and is between 4ms and 16ms in Chrome, and about 2ms in Safari. Pretty strange stuff!
Incidentally, this also shows us the accuracy of various browsers’ setTimeouts. Chrome seems pretty spot-on — but I’d personally prefer to code in an environment with useful variable logging than one with ms-precision timeouts






