O console JavaScript do Chrome é preguiçoso na avaliação de matrizes?

Vou começar com o código:

var s = ["hi"]; console.log(s); s[0] = "bye"; console.log(s); 

Simples, certo? Em resposta a isso, o Firebug diz:

 ["hi"] ["bye"] 

Maravilhoso, mas o console JavaScript do Chrome (7.0.517.41 beta) diz:

 ["bye"] ["bye"] 

Eu fiz algo errado, ou o console JavaScript do Chrome está sendo extremamente preguiçoso em avaliar meu array?

insira a descrição da imagem aqui

Obrigado pelo comentário, tec. Eu era capaz de encontrar um bug Webkit não confirmado existente que explica este problema: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDIT: agora corrigido!)

Parece haver algum debate sobre o quanto de um bug é e se é solucionável. Parece mau comportamento para mim. Isso foi especialmente problemático para mim porque, pelo menos no Chrome, ocorre quando o código reside em scripts que são executados imediatamente (antes que a página seja carregada), mesmo quando o console está aberto, sempre que a página é atualizada. Chamar console.log quando o console ainda não está ativo resulta apenas em uma referência ao object que está sendo enfileirado, não na saída que o console conterá. Portanto, a matriz (ou qualquer object) não será avaliada até que o console esteja pronto. É realmente um caso de avaliação preguiçosa.

No entanto, há uma maneira simples de evitar isso no seu código:

 var s = ["hi"]; console.log(s.toString()); s[0] = "bye"; console.log(s.toString()); 

Ao chamar toString, você cria uma representação na memory que não será alterada seguindo as instruções, que o console lerá quando estiver pronto. A saída do console é um pouco diferente de passar o object diretamente, mas parece aceitável:

 hi bye 

A partir da explicação de Eric, é devido a console.log() sendo enfileirada, e ela imprime um valor posterior da matriz (ou object).

Pode haver 5 soluções:

 1. arr.toString() // not well for [1,[2,3]] as it shows 1,2,3 2. arr.join() // same as above 3. arr.slice(0) // a new array is created, but if arr is [1, 2, arr2, 3] // and arr2 changes, then later value might be shown 4. arr.concat() // a new array is created, but same issue as slice(0) 5. JSON.stringify(arr) // works well as it takes a snapshot of the whole array // or object, and the format shows the exact structure 

Você pode clonar um array com o array Array#slice :

 console.log(s); // ["bye"], ie incorrect console.log(s.slice()); // ["hi"], ie correct 

Uma function que você pode usar em vez de console.log que não tem esse problema é a seguinte:

 console.logShallowCopy = function () { function slicedIfArray(arg) { return Array.isArray(arg) ? arg.slice() : arg; } var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray); return console.log.apply(console, argsSnapshot); }; 

Para o caso de objects, infelizmente, o melhor método parece ser depurar primeiro com um navegador não-WebKit ou escrever uma function complicada para clonar. Se você está trabalhando apenas com objects simples, onde a ordem das chaves não importa e não há funções, você sempre pode fazer:

 console.logSanitizedCopy = function () { var args = Array.prototype.slice.call(arguments); var sanitizedArgs = JSON.parse(JSON.stringify(args)); return console.log.apply(console, sanitizedArgs); }; 

Todos esses methods são obviamente muito lentos, então, mais ainda do que com o console.log normal, você precisa desmembrá-los depois de concluir a debugging.

Isso foi corrigido no Webkit, no entanto, ao usar o framework React isso acontece para mim em algumas circunstâncias, se você tiver esses problemas, use apenas como os outros sugerem:

 console.log(JSON.stringify(the_array)); 

Isso já está respondido, mas vou deixar minha resposta de qualquer maneira. Eu implementei um simples wrapper de console que não sofre com esse problema. Requer jQuery.

Ele implementa somente methods de log , warn e error , você terá que adicionar mais alguns para que seja intercambiável com um console normal.

 var fixedConsole; (function($) { var _freezeOne = function(arg) { if (typeof arg === 'object') { return $.extend(true, {}, arg); } else { return arg; } }; var _freezeAll = function(args) { var frozen = []; for (var i=0; i 

Parece que o Chrome está substituindo em sua fase de “pré-compilation” qualquer instância de “s” com ponteiro para a matriz real.

Uma maneira é clonar a matriz, registrando uma nova cópia:

 var s = ["hi"]; console.log(CloneArray(s)); s[0] = "bye"; console.log(CloneArray(s)); function CloneArray(array) { var clone = new Array(); for (var i = 0; i < array.length; i++) clone[clone.length] = array[i]; return clone; }