Hola Hoy te diré cómo usar el depurador para resolver, en mi opinión, un problema de JavaScript no trivial.En JavaScript, los objetos son un tipo de datos compuesto; su valor se pasa por referencia. En otras palabras, cuando pasamos un objeto a una función como parámetro, o en cualquier lugar, podemos cambiar sus propiedades. Usando una instrucción que consiste en una expresión variable que almacena un enlace, así como operadores de punto y asignación. Después de eso, otras instrucciones que funcionan o funcionarán con esta variable / parámetro recibirán un cambio de propiedad por referencia.
A menudo, este comportamiento distorsiona los datos del usuario, conduce a errores y no es deseable.
Encontrar la fuente de tales cambios de propiedad no deseados puede llevar mucho tiempo: por lo tanto, el programa puede ser grande y constar de cientos de miles de instrucciones.
Veamos un ejemplo simple.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Debug property mutation example</title> <script> const user = { firstName: 'Vasilij', middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } }; </script> <script src="object-property-mutation.js" type="application/javascript"></script> </head> </head> <body> <script> Promise.resolve(user).then(user.getFullName.bind(user)).then(console.log); </script> </body> </html>
Ahora el programa web no funciona, porque hay un error en la consola y no hay salida del nombre.

Leemos el mensaje superior en la consola:
Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined
Un error como: no se procesó (como promesa): no puedo leer la propiedad de división desde indefinido.
Haga clic en el enlace y vaya al lugar del error.
getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` }
Vemos que la expresión errónea
this.firstName.slice(0, 1)
consta de cuatro operadores:
- dos operadores de puntos
- un separador de coma
- un operador de agrupación - un par de paréntesis
Leamos las instrucciones. La expresión izquierda se evalúa primero
this.firstName
Consiste en un operador de puntos, a la izquierda, la expresión primaria de esto, y el identificador firstName a la derecha. El resultado de esta expresión será indefinido. La ejecución de la siguiente declaración de puntos provoca un error. Dado que el operador de punto solo funciona con tipos de objeto, su ejecución desde indefinido conduce a un error: no puedo obtener la propiedad de división desde indefinido.
Resulta que en algún lugar esta propiedad se configuró como indefinida ...
Para resolver este problema, intentemos lo contrario. Utilizaremos la herramienta de depuración para
detener la excepción . Moviéndonos desde el lugar del error hacia abajo en la pila de llamadas, intentamos pasar a la instrucción que cambió la propiedad.
Seleccione la herramienta detener en excepción

Vemos que solo hay dos llamadas en la pila. Ir a la llamada anterior.

Vemos que no hay instrucciones explícitas que cambien la propiedad firstName.

Concluimos que el cambio no ocurre en esta pila de llamadas.
Como te gusta eso
¿Y cómo encontrar al villano que cambió la propiedad de mi objeto?
Por favor escriba en los comentarios cómo lo encontraría?
Chicos que trabajan conmigo y a quienes les dije, por favor escriban un asterisco en el comentario.
Estoy muy interesado en saber cómo otros especialistas de JavaScript resuelven estos problemas.
Sabes, cuando encontré por primera vez este comportamiento de JavaScript, pasé un par de horas investigando y arrancándome un mechón de pelo de mi flequillo ...
Deshabilite la herramienta de pausa en la excepción.
Entonces, aquí está nuestro nuevo plan, definiremos la propiedad firstName en el objeto de usuario usando getter y setter.
Agregamos la declaración de depuración al configurador usando la declaración del depurador y la declaración de punto y coma.
const user = { _firstName: 'Vasilij', set firstName(value) { debugger; this._firstName = value; }, get firstName() {return this._firstName}, middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.`; } };
Avanzando a lo largo de la pila de llamadas, encontramos una instrucción que cambia la propiedad firstName.
El depurador se detuvo en el setter antes de que el nuevo valor se escriba en el objeto.

Vemos que el valor del valor del parámetro no está definido.
Ahora, usando la pila de llamadas, podemos pasar fácilmente a la llamada anterior.

iiiii, victoria aaaaaah.
Hay una manera aún más simple de resolver este problema utilizando la herramienta de depuración
deteniéndose en una excepción .
Aquí está nuestro nuevo plan: haremos que el objeto del usuario no sea un objeto y, utilizando la herramienta de
detención por excepción , podemos llegar fácilmente a las instrucciones erróneas.
Como sabemos que al intentar obtener una propiedad indefinida se produce un error.
Activamos la herramienta de detención de excepciones, configuramos la variable de usuario como indefinida.
const user = undefined;
Nuevamente nos detuvimos en el lugar donde la propiedad firstName estaba distorsionada.

Eso es todo lo que quería decirte hoy sobre la depuración de cambios no deseados en los objetos.
Gracias por leer el artículo. Dale me gusta, suscríbete al canal, comparte este video y artículo con amigos, todo lo mejor.
github.com/NVBespalov/js-lessons/tree/error/property-mutation