33

Ich half einem Kollegen heute einige Code debuggen und ich bemerkte ein seltsames Verhalten mit console.log() in Google Chrome:Google Chrome console.log() Inkonsistenz mit Objekten und Arrays

Es scheint, dass, wenn Sie:

  1. erstellen einer verschachtelten Array (zB [[345, "test"]])

  2. Log das Array an der Konsole mit console.log().

  3. Ändern eines der inneren Datenfeldwerte, dann console.log() ausgeben wird der spätere Wert - nicht die Werte des Arrays zu der Zeit der console.log() wurde ausgeführt.

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

Dieses Verhalten tritt nicht in Firefox.

Auch, wenn ich im Code Debugger Zeile für Zeile durch seinen Code trat, dann würde console.log() die richtigen Werte ausgeben.

Gibt es eine Erklärung für dieses seltsame Phänomen oder ist es nur ein Bug mit Google Chrome?

EDIT:

Ich habe die Schritte verengt, um die inkonsistenten console.log() Verhalten zu reproduzieren:

Wenn Sie dieses Skript zu Ihrer Seite hinzufügen:

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

und öffnen Sie sie in Ein neues Fenster mit dem bereits geöffneten Konsolenfenster , dann ist die Ausgabe console.log() anders als beim Laden der Seite mit dem Konsolenfenster geschlossen. Here's a JSFiddle that demonstrates that.

Im ersten Fall, bei bereits geöffnetem Konsolenfenster, gibt console.log() den aktuellen Wert des Arrays (d. H. Zwei Elemente) aus.

Im zweiten Fall, mit dem Fenster Konsole zunächst geschlossen und erst nach Laden der Seite geöffnet, console.log() ausgeben wird die späteren Werte des Arrays (d.h. drei Artikel).

Ist dies ein Fehler in Google Chrome console.log() Funktionalität?

+0

Obwohl ich weiß nicht, wie genau dies ist kein Fehler, tut Chrome diese Art der Sache mit einer gewissen Häufigkeit; Sie können auch das Ergebnis einer AJAX-Anfrage protokollieren; Es füllt es rückwirkend aus, vermutlich zur besseren Übersichtlichkeit beim Logging. Ich bin zu unerfahren, um zu erklären, warum, ich hatte gerade ein ähnliches Problem, mich zu verwirren.Jeglicher Code, der von dem korrekten Wert abhing, würde jedoch gut funktionieren. – Jonline

+1

Es scheint, dass der in der Konsole protokollierte Wert etwas von einem * live * -Wert ist. Jeder Skalarwert innerhalb von Referenzobjekten wird nicht berechnet, bis Sie die betreffenden Objekte in der Konsolenausgabe expandieren. – Phil

+0

Es erscheint seltsam, dass die Ergebnisse einer 'console.log()' einer race-Bedingung unterliegen. Wenn ich meinen Kollegen-Code durchging, würde die 'console.log()' die von uns erwarteten Werte ausgeben, aber bei normaler Ausführung würde sie einen späteren modifizierten Wert ausgeben - scheint so, als würden Sie die Werte des Arrays bei wollen der genaue Moment, in dem 'console.log()' ausgeführt wird. –

Antwort

26

Nach vielen Ausgrabungen habe ich festgestellt, dass dies als Fehler in Webkit gemeldet wurde, aber anscheinend noch nicht in Google Chrome gezogen wurde.

Soweit ich das beurteilen kann, wurde das Thema ursprünglich hier berichtet: https://bugs.webkit.org/show_bug.cgi?id=35801:

Beschreibung Von mitch kramer 2010-03-05 11.37.45 PST

1) ein Objekt erstellen wörtliche mit einer oder mehrer Eigenschaften

2) console.log das Objekt aber lassen sie es (nicht erweitert es in der Konsole)

3) ändert eine der Eigenschaften auf einen neuen Wert geschlossen

Jetzt öffnen Sie diese console.log und Sie werden sehen, es hat den neuen Wert aus irgendeinem Grund, auch wenn der Wert zum Zeitpunkt der Generierung unterschiedlich war.

Ich sollte darauf hinweisen, dass wenn Sie es öffnen, behält es den richtigen Wert, wenn das nicht klar war.

Antwort von einem Chromium-Entwickler:

Kommentar # 2 von Pavel Feldman 2010-03-09 06.33.36 PST

Ich glaube nicht, werden wir jemals beheben dieses. Wir können das Objekt nicht klonen, nachdem wir es in die Konsole geladen haben, und wir können auch nicht auf die Änderungen der Objekteigenschaften hören, um sie immer aktuell zu machen.

Wir sollten sicherstellen, dass bereits vorhandenes Verhalten erwartet wird.

Ein Fix war umgesetzt zweieinhalb Jahre später, am 9. August 2012 für Webkit (http://trac.webkit.org/changeset/125174), aber es scheint nicht, es noch in Chrome gemacht zu haben.

Bis heute führt ein Objekt (Array) in die Konsole dumping in Objekteigenschaften lesen auf Konsolen-Objekt Expansion ist (d.h. lazily). Dies bedeutet, dass das gleiche Objekt zu entladen ist, während mutiert wird es schwierig sein, mit der Konsole zu debuggen.

Diese Änderung startet die Erstellung von verkürzten Vorschauen für Objekte/Arrays zum Zeitpunkt ihrer Protokollierung und übergibt diese Informationen an das Front-End. Dies geschieht nur, wenn das Front-End bereits geöffnet ist, es funktioniert nur für console.log(), nicht Live-Konsole-Interaktion.

+0

"Dies bedeutet, dass das gleiche Objekt während der Mutation Dumping wird schwer sein mit der Konsole zu debuggen ", habe ich erst vor ein paar Monaten bemerkt und es hat mich verrückt gemacht. – Fahmi

+0

Danke. Ich habe mir in den letzten Tagen die Haare ausgezogen, um herauszufinden, was mit meinem Code nicht stimmt. Hier war es ein Problem mit Chrome die ganze Zeit. – kojow7

+2

Sein 2017 und es passiert immer noch mit geschachtelten Objektwerten. Ich verbrachte gestern Stunden damit, ein Encoding-Plugin zu debuggen, weil es mir die Werte nicht gezeigt hat. Es stellte sich heraus, dass es Chrom war, als ich die Obj-Zuweisung und das verschachtelte Objekt vorher/nachher protokollierte. – OneEyed

3

Ich habe einen Workaround für diesen Bug/Feature gefunden.

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

Edit: Leider funktioniert dies nicht für nicht-primitive Werte wie Funktionen. Verwenden Sie hier ein anderes Klon-Dienstprogramm.

jQuery Beispiel:

console.log($.extend({}, myObject)); 
+0

Gute Idee! Sie könnten auch die Funktion 'toString' überschreiben –

+0

Leider können nicht alle Objekte mit einem String versehen werden. z. B. die Datei "JSON.stringify (document.body)" – ahui

Verwandte Themen