Recherche rapide de la source des mutations indésirables d'une propriété d'objet

Salut Aujourd'hui, je vais vous expliquer comment utiliser le débogueur pour résoudre, à mon avis, un problème JavaScript non trivial.

En JavaScript, les objets sont un type de données composite; sa valeur est transmise par référence. En d'autres termes, lorsque nous passons un objet dans une fonction en tant que paramètre, ou n'importe où nous pouvons changer ses propriétés. Utilisation d'une instruction composée d'une expression variable stockant un lien, ainsi que des opérateurs de points et d'affectation. Après cela, d'autres instructions qui fonctionnent ou fonctionneront avec cette variable / paramètre recevront une modification de propriété par référence.

Souvent, ce comportement déforme les données utilisateur, conduit à des erreurs et n'est pas souhaitable.

Trouver la source de ces modifications de propriétés indésirables peut prendre beaucoup de temps: le programme peut donc être déjà volumineux et se composer de centaines de milliers d'instructions.

Regardons un exemple 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> 

Maintenant, le programme Web ne fonctionne pas, car il y a une erreur dans la console et il n'y a pas de sortie du nom complet.

image

Nous lisons le message le plus haut dans la console:

 Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined 

Une erreur comme: n'a pas été traitée (comme promesse): je ne peux pas lire la propriété slice à partir d'undefined.

Cliquez sur le lien et accédez au lieu de l'erreur.

 getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } 

Nous voyons que l'expression erronée
 this.firstName.slice(0, 1) 
se compose de quatre opérateurs:

  1. deux opérateurs point
  2. un séparateur de virgule
  3. un opérateur de regroupement - une paire de parenthèses

Lisons les instructions. L'expression de gauche est évaluée en premier

 this.firstName 

Il se compose d'un opérateur point, à gauche l'expression principale de celui-ci, et de l'identifiant firstName à droite. Le résultat de cette expression ne sera pas défini. L'exécution de l'instruction dot suivante provoque une erreur. Étant donné que l'opérateur point ne fonctionne qu'avec des types d'objet, son exécution à partir de non défini entraîne une erreur - je ne peux pas obtenir la propriété slice à partir de non défini.

Il s'avère que quelque part cette propriété a été définie sur undefined ...

Pour résoudre ce problème, essayons le contraire. Nous utiliserons l'outil de débogage pour arrêter l'exception . En déplaçant le lieu de l'erreur vers le bas de la pile d'appels, nous essayons de passer à l'instruction qui a changé la propriété.

Sélectionnez l'outil Stop on Exception


image

Nous voyons qu'il n'y a que deux appels dans la pile. Allez à l'appel précédent.

image

Nous voyons qu'aucune instruction explicite ne modifie la propriété firstName.

image

Nous concluons que le changement ne se produit pas dans cette pile d'appels.

Comment aimez-vous ça?


Et comment retrouver le méchant qui a changé la propriété de mon objet?

Veuillez écrire dans les commentaires comment le trouveriez-vous?
Les gars qui travaillent avec moi et à qui je vous ai dit, veuillez écrire un astérisque dans le commentaire.

Je suis très intéressé de savoir comment d’autres spécialistes JavaScript résolvent de tels problèmes.

Vous savez, quand j'ai rencontré ce comportement JavaScript pour la première fois, j'ai passé quelques heures à enquêter et à arracher une touffe de cheveux de ma frange ...

Désactivez l'outil de pause sur exception.

Donc, voici notre nouveau plan, nous allons définir la propriété firstName dans l'objet utilisateur en utilisant le getter et le setter.

Nous ajoutons l'instruction de débogage au setter à l'aide de l'instruction de débogage et de l'instruction point-virgule.

 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)}.`; } }; 

Plus loin dans la pile des appels, nous trouvons une instruction qui modifie la propriété firstName.

Le débogueur s'est arrêté dans le setter avant que la nouvelle valeur ne soit écrite dans l'objet.

image

Nous voyons que la valeur de la valeur du paramètre n'est pas définie.

Maintenant, en utilisant la pile d'appels, nous pouvons facilement passer à l'appel précédent.

image

iiiii, victoire aaaaaah.

Il existe un moyen encore plus simple de résoudre ce problème en utilisant l'outil de débogage en arrêtant l'exception .

Voici notre nouveau plan: faisons de l'objet utilisateur non un objet et, en utilisant l'outil d' arrêt par exception , nous pouvons facilement accéder à l'instruction erronée.

Puisque nous savons que lorsque vous essayez d'obtenir une propriété non définie, une erreur se produit.

Nous activons l'outil d'arrêt d'exception, définissons la variable utilisateur sur undefined.

  const user = undefined; 

Nous nous sommes de nouveau arrêtés à l'endroit où la propriété firstName a été déformée.

image

C'est tout ce que je voulais vous dire aujourd'hui sur le débogage des modifications indésirables sur les objets.

Merci d'avoir lu l'article. Comme, abonnez-vous à la chaîne, partagez cette vidéo et cet article avec vos amis, tout le meilleur.

github.com/NVBespalov/js-lessons/tree/error/property-mutation

Source: https://habr.com/ru/post/fr481824/


All Articles