console.log() muestra el valor modificado de una variable antes de que el valor realmente cambie
Este fragmento de código lo entiendo. Hacemos una copia de A y la llamamos C. Cuando se cambia A, C permanece igual
var A = 1;
var C = A;
console.log(C); // 1
A++;
console.log(C); // 1
Pero cuando A es una matriz tenemos una situación diferente. C no solo cambiará, sino que cambiará incluso antes de que toquemos A.
var A = [2, 1];
var C = A;
console.log(C); // [1, 2]
A.sort();
console.log(C); // [1, 2]
¿Alguien puede explicar lo que pasó en el segundo ejemplo?
console.log()
Se pasa una referencia al objeto, por lo que el valor en la consola cambia a medida que cambia el objeto. Para evitarlo puedes:
console.log(JSON.parse(JSON.stringify(c)))
MDN advierte :
Tenga en cuenta que si registra objetos en las últimas versiones de Chrome y Firefox, lo que se registra en la consola es una referencia al objeto, que no es necesariamente el "valor" del objeto en el momento en que llama,
console.log()
pero es el valor del objeto en el momento en que abres la consola.
La respuesta de Pointy tiene buena información, pero no es la respuesta correcta para esta pregunta.
El comportamiento descrito por el OP es parte de un error que se informó por primera vez en marzo de 2010, parcheado para Webkit en agosto de 2012, pero al momento de escribir este artículo aún no está integrado en Google Chrome. El comportamiento depende de si la ventana de depuración de la consola está abierta o cerrada en el momento en que se pasa el objeto literal console.log()
.
Extractos del informe de error original ( https://bugs.webkit.org/show_bug.cgi?id=35801 ):
Descripción De mitch kramer 2010-03-05 11:37:45 PST
1) crear un objeto literal con una o más propiedades
2) console.log ese objeto pero déjalo cerrado (no lo expandas en la consola)
3) cambiar una de las propiedades a un nuevo valor
ahora abra ese console.log y verá que tiene el nuevo valor por alguna razón, aunque su valor era diferente en el momento en que se generó.
Debo señalar que si lo abre, conservará el valor correcto si no quedó claro.
Respuesta de un desarrollador de Chromium:
Comentario n.º 2 de Pavel Feldman 2010-03-09 06:33:36 PST
No creo que alguna vez vayamos a solucionar este problema. No podemos clonar el objeto al volcarlo en la consola y tampoco podemos escuchar los cambios de las propiedades del objeto para que siempre sea actual.
Sin embargo, debemos asegurarnos de que se espere el comportamiento existente.
Surgieron muchas quejas y finalmente se solucionó el error.
Notas del registro de cambios del parche implementado en agosto de 2012 ( http://trac.webkit.org/changeset/125174 ):
A partir de hoy, volcar un objeto (matriz) en la consola dará como resultado que las propiedades de los objetos se lean al expandirse el objeto de la consola (es decir, de forma perezosa). Esto significa que deshacerse del mismo objeto mientras se muta será difícil de depurar usando la consola.
Este cambio comienza a generar vistas previas abreviadas para objetos/matrices en el momento de su registro y pasa esta información al front-end. Esto solo sucede cuando el front-end ya está abierto, solo funciona para console.log(), no para la interacción de la consola en vivo.
Actualizado el 9 de marzo de 2023
La última orientación de Mozilla a marzo de 2023:
La información sobre un objeto se recupera de forma diferida. Esto significa que el mensaje de registro muestra el contenido de un objeto en el momento en que se ve por primera vez, no cuando se registró. Por ejemplo:
const obj = {};
console.log(obj);
obj.prop = 123;
Esto generará {}
. Sin embargo, si amplía los detalles del objeto, verá prop: 123
.
Si va a mutar su objeto y desea evitar que se actualice la información registrada, puede realizar una clonación profunda del objeto antes de registrarlo. Una forma común es JSON.stringify()
y luego JSON.parse()
:
console.log(JSON.parse(JSON.stringify(obj)));
Existen otras alternativas que funcionan en navegadores, como structuredClone()
, que son más efectivas a la hora de clonar diferentes tipos de objetos.
const mushrooms1 = {
amanita: ["muscaria", "virosa"],
};
const mushrooms2 = structuredClone(mushrooms1);
mushrooms2.amanita.push("pantherina");
mushrooms1.amanita.pop();
console.log(mushrooms2.amanita); // ["muscaria", "virosa", "pantherina"]
console.log(mushrooms1.amanita); // ["muscaria"]
Orientación anterior de MDN
La última orientación de Mozilla a febrero de 2023:
No usar
console.log(obj)
, usarconsole.log(JSON.parse(JSON.stringify(obj)))
.De esta manera estará seguro de que está viendo el valor de
obj
en el momento en que lo registra. De lo contrario, muchos navegadores ofrecen una vista en vivo que se actualiza constantemente a medida que cambian los valores. Puede que esto no sea lo que quieres.