59

I was helping a colleague debug some code today and I noticed a strange behavior with console.log() in Google Chrome:

It appears that if you:

  1. Create a nested array (e.g., [[345,"test"]])

  2. Log the array to the console with console.log().

  3. Modify one of the inner array values, then console.log() will output the later value -- not the values of the array at the time the console.log() was executed.

JavaScript:

var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]

var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}


var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]

JSFiddle Example

This behavior does not happen in Firefox.

Also to note, if I stepped through his code line by line in the Chrome debugger, then console.log() would output the correct values.

Is there an explanation for this strange phenomenon or is it just a bug with Google Chrome?

EDIT:

I've narrowed down the steps to reproduce the inconsistent console.log() behavior:

If you add this script to your page:

var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
    greetings.push('goodbye');
},3000);

and open it in a new window with the Chrome console window already open, then the console.log() output will be different than if you load the page with the console window closed. Here's a JSFiddle that demonstrates that.

In the first case, with the console window already open, console.log() will output the current value of the array (i.e., two items).

In the second case, with the console window initially closed and opened only after the page loads, console.log() will output the later values of the array (i.e., three items).

Is this a bug in Google Chrome's console.log() functionality?

Elliot B.
  • 17,060
  • 10
  • 80
  • 101
  • Though I don't know how, exactly, this isn't a bug, Chrome does this sort of thing with some frequency; you can log the result of an AJAX request, too; it retroactively fills it in, presumably for clarity when logging. I am too inexpert to begin to explain why, I've just had a similar problem confound me. Any code that depended on the correct value would operate fine, though. – Jonline Jun 12 '14 at 01:13
  • 1
    It appears that the value logged to the console is something of a *live* value. Any scalar value within reference objects won't be calculated until you expand the objects in question within the console output – Phil Jun 12 '14 at 01:14
  • 1
    It seems strange that the results of a `console.log()` would be subject to something like a race condition. When I was stepping through my colleagues code, the `console.log()` would output the values we expected, but with normal execution, it would output a later modified value -- seems like you'd want the values of the array at the precise moment `console.log()` is executed. – Elliot B. Jun 12 '14 at 01:15
  • 3
    it's not a bug, Chrome intentionally makes console.log display the live value – markasoftware Jun 12 '14 at 01:17
  • @ElliotB if you want specific (scalar) values logged, then I suggest you log those instead of their parent objects, ie `console.log(test[0][0])` – Phil Jun 12 '14 at 01:17
  • Maybe the value isn't grabbed until the object is expanded or the log function is asynchronous in the background. The workaround is to log the members: console.log(test[0]); – Steve Wellens Jun 12 '14 at 01:17
  • 2
    possible duplicate of [console.log() shows the changed value of a variable before the value actually changes](http://stackoverflow.com/questions/11284663/console-log-shows-the-changed-value-of-a-variable-before-the-value-actually-ch) – Anonymous Jun 12 '14 at 01:18
  • Seems like the "problem" isn't chrome-specific: It occur in Safari too. It may be from Webkit itself. – Tiago Marinho Jun 12 '14 at 01:19
  • @ElliotB. If you want screenshots included, please include them as actual screenshots using the image upload feature, not as links; also, I've edited your question to do two things 1) have it comply with our requirements for questions 2) taking the answer out of the question. If you have an answer, please post it as such. – George Stocker Jun 12 '14 at 16:01
  • This apparently is **not** a feature, as my answer stated, even though it seems like one, so I guess I'll be deleting my answer now – markasoftware Jun 12 '14 at 22:41

2 Answers2

44

After a lot of digging, I found that this has been reported as a bug, fixed in Webkit, but apparently not yet pulled into Google Chrome.

As far as I can tell, the issue was originally reported here: https://bugs.webkit.org/show_bug.cgi?id=35801 :

Description From mitch kramer 2010-03-05 11:37:45 PST

1) create an object literal with one or more properties

2) console.log that object but leave it closed (don't expand it in the console)

3) change one of the properties to a new value

now open that console.log and you'll see it has the new value for some reason, even though it's value was different at the time it was generated.

I should point out that if you open it, it will retain the correct value if that wasn't clear.

Response from a Chromium developer:

Comment #2 From Pavel Feldman 2010-03-09 06:33:36 PST

I don't think we are ever going to fix this one. We can't clone object upon dumping it into the console and we also can't listen to the object properties' changes in order to make it always actual.

We should make sure existing behavior is expected though.

A fix was implemented two and a half years later on August 9th, 2012 for Webkit ( http://trac.webkit.org/changeset/125174 ), but it does not appear to have made it into Chrome yet.

As of today, dumping an object (array) into console will result in objects' properties being read upon console object expansion (i.e. lazily). This means that dumping the same object while mutating it will be hard to debug using the console.

This change starts generating abbreviated previews for objects / arrays at the moment of their logging and passes this information along into the front-end. This only happens when the front-end is already opened, it only works for console.log(), not live console interaction.

Elliot B.
  • 17,060
  • 10
  • 80
  • 101
  • 1
    "This means that dumping the same object while mutating it will be hard to debug using the console", I just realized this few months ago and it drove me crazy. – Fahmi Feb 07 '17 at 18:50
  • Thank you. I've been pulling my hair out for the last couple of days trying to figure this out what was wrong with my code. Here it was an issue with Chrome all along. – kojow7 Jul 24 '17 at 07:58
  • 8
    Its 2017 and its still happening with nested object values. I spent hours yesterday debugging an encoding plugin because it wasnt showing me the values, turns out it was chrome when I logged the obj assignment and nested obj before/after. – JoeOfTex Sep 27 '17 at 14:31
  • 2
    I see the same problem persists in 2021. – D Park Jun 19 '21 at 15:37
  • 1
    Hi from 2021, I can see this bug with console.log() when using a fetch Response with TypeScript to begin with. I find that hover over said array with mouse displays help text "object" which makes typing in typescript not completely fail. – Erkka Mutanen Jul 15 '21 at 07:28
20

I found a workaround for this bug/feature.

console.log(JSON.parse(JSON.stringify(myObject)));

Edit: Unfortunately this won't work for non-primitive values like functions. Use another clone utility here.

jQuery example:

console.log($.extend({}, myObject));
cheeZer
  • 460
  • 1
  • 8
  • 15