sirve - ver codigo javascript de una pagina
¿La consola de JavaScript de Chrome es vaga sobre la evaluación de matrices? (6)
Comenzaré con el código:
var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
Simple, ¿verdad? En respuesta a esto, Firebug dice:
["hi"]
["bye"]
Maravilloso, pero la consola de JavaScript de Chrome (7.0.517.41 beta) dice:
["bye"]
["bye"]
¿He hecho algo mal, o la consola de Chrome de Chrome es excepcionalmente vago para evaluar mi matriz?
De la explicación de Eric, se debe a que console.log()
está en cola, e imprime un valor posterior de la matriz (u objeto).
Puede haber 5 soluciones:
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
Esto ha sido parcheado en Webkit; sin embargo, cuando se usa el framework React, esto sucede para mí en algunas circunstancias, si tiene tales problemas simplemente use como otros sugieren:
console.log(JSON.stringify(the_array));
Esto ya está respondido, pero dejaré mi respuesta de todos modos. Implementé un envoltorio de consola simple que no sufre este problema. Requiere jQuery.
Implementa solo métodos de log
, warn
y error
, tendrá que agregar algunos más para que sea intercambiable con una 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<args.length; i++) {
frozen.push(_freezeOne(args[i]));
}
return frozen;
};
fixedConsole = {
log: function() { console.log.apply(console, _freezeAll(arguments)); },
warn: function() { console.warn.apply(console, _freezeAll(arguments)); },
error: function() { console.error.apply(console, _freezeAll(arguments)); }
};
})(jQuery);
Gracias por el comentario, tec. Pude encontrar un error Webkit no confirmado que explica este problema: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDIT: ¡ahora corregido!)
Parece que hay un poco de debate con respecto a la cantidad de error que es y si es corregible. Me parece un mal comportamiento. Me resultó especialmente preocupante porque, al menos en Chrome, ocurre cuando el código reside en scripts que se ejecutan inmediatamente (antes de que se cargue la página), incluso cuando la consola está abierta, cada vez que se actualiza la página. Llamar a console.log cuando la consola aún no está activa solo da como resultado una referencia al objeto que está en cola, no la salida que contendrá la consola. Por lo tanto, la matriz (o cualquier objeto) no se evaluará hasta que la consola esté lista. Realmente es un caso de evaluación perezosa.
Sin embargo, hay una manera simple de evitar esto en tu código:
var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
Al llamar a String, crea una representación en la memoria que no será alterada por las siguientes declaraciones, que la consola leerá cuando esté lista. La salida de la consola es ligeramente diferente de pasar el objeto directamente, pero parece aceptable:
hi
bye
Parece que Chrome está reemplazando en su fase de "pre compilación" cualquier instancia de "s" con un puntero a la matriz real.
Una forma de evitarlo es clonando la matriz, registrando una copia nueva en su lugar:
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;
}
Puede clonar una matriz con Array#slice
:
console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
Una función que puede usar en lugar de console.log
que no tiene este problema es la siguiente:
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 el caso de los objetos, desafortunadamente, el mejor método parece ser primero depurar con un navegador que no sea WebKit, o escribir una función complicada para clonar. Si solo trabaja con objetos simples, donde el orden de las claves no importa y no hay funciones, siempre puede hacer:
console.logSanitizedCopy = function () {
var args = Array.prototype.slice.call(arguments);
var sanitizedArgs = JSON.parse(JSON.stringify(args));
return console.log.apply(console, sanitizedArgs);
};
Todos estos métodos son, obviamente, muy lentos, por lo que incluso más que con console.log
s normal, tienes que quitarlos después de que hayas terminado de depurar.