Google Chrome console.log() inconsistency with obj

2019-01-01 04:08发布

问题:

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?

回答1:

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.



回答2:

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));