Observer le comportement de programmes via le débogueur, suivre les variables, comprendre les erreurs de logique ou de portée, corriger et optimiser les fonctions.
EXERCICE 1
Ce que j’ai appris :
J’ai appris à utiliser un point d’arrêt dans une boucle pour suivre l’évolution d’une variable. Cela permet de visualiser chaque étape de son changement et de mieux comprendre la logique de l’algorithme.
EXERCICE 2
Ce que j’ai appris :
J’ai appris à suivre le remplissage dynamique d’un tableau dans une boucle, et à utiliser les outils de débogage pour observer l’évolution du contenu de ce tableau en temps réel.
EXERCICE 3
Pourquoi cela ne fonctionne pas comme prévu :
Le programmeur pensait échanger les valeurs de x et y, mais comme les paramètres sont passés par valeur, les modifications dans la fonction ne changent pas les valeurs extérieures. L’échange se fait uniquement sur des copies locales.
Ce que j’ai appris :
J’ai appris que les types primitifs comme les nombres sont passés par valeur. Modifier une variable dans une fonction ne modifie pas la variable d’origine, contrairement aux objets.
EXERCICE 4
Pourquoi ça marche :
Le tableau est passé par référence, donc les modifications apportées dans la fonction affectent directement le tableau d’origine. C’est pour cela que l’échange est visible à l’extérieur.
Affichage du dernier console.log :
Même si on écrit xy = [100, 200] dans la fonction, le dernier console.log en dehors affiche les valeurs modifiées initialement (ex : [20, 10]). Cela s’explique par le fait que l’instruction xy = [100, 200] redirige la variable locale vers un nouveau tableau sans affecter la référence d’origine.
Ce que j’ai appris :
J’ai appris que les tableaux sont des objets passés par référence. On peut modifier leur contenu dans une fonction, mais les réassigner ne change pas le tableau d’origine.
EXERCICE 5
États successifs de la mémoire :
- j global vaut 10.
- j dans la fonction deb4 vaut 25.
- j dans la boucle for est redéfini à chaque tour comme 2 * i.
Il y a donc trois variables distinctes nommées j, chacune avec sa propre portée.
Portée des variables :
Chaque j est défini dans un bloc différent (global, fonction, boucle). Grâce à let, il n’y a pas de conflit entre les variables, car elles ne partagent pas le même espace mémoire.
Ce que j’ai appris :
J’ai appris que let crée une variable locale propre à chaque bloc. On peut utiliser le même nom dans différents contextes sans collision.
EXERCICE 6
Ce qui se passe ligne 2 et différence entre les deux programmes :
Dans le premier cas (avec var), la variable est hoistée en haut du script, donc le console.log affiche undefined.
Dans le second cas (avec let), la variable est en zone morte temporaire, donc le console.log provoque une erreur.
Cela montre que var autorise l’accès à une variable non encore initialisée, alors que let le bloque.
Ce que j’ai appris :
J’ai appris la différence entre var et let : var subit un hoisting complet avec initialisation undefined, tandis que let bloque tout accès tant qu’il n’est pas déclaré, ce qui rend le code plus sûr.
EXERCICE 7
Ce que j’ai appris :
J’ai appris à simuler une multiplication manuellement en utilisant une boucle d’additions. J’ai aussi appris à gérer les cas où les opérandes sont négatifs, sans utiliser de fonctions comme Math.abs, et à simplifier le code tout en conservant un comportement correct pour tous les cas.
EXERCICE 8
États successifs de la mémoire :
Chaque appel récursif de la fonction crée une nouvelle case dans la pile d’exécution avec une valeur différente de n.
Par exemple, pour n = 5, la pile ressemble à :
- n = 5 (en attente de deb8(4))
- n = 4 (en attente de deb8(3))
- n = 3 (en attente de deb8(2))
- n = 2 (en attente de deb8(1))
- n = 1 (en attente de deb8(0))
- n = 0 (retourne 1)
Ensuite, les appels se terminent les uns après les autres en multipliant les valeurs retournées, jusqu'à obtenir le résultat final.
Ce que j’ai appris :
J’ai appris comment fonctionne une fonction récursive en mémoire : chaque appel est empilé dans la pile d’exécution avec ses propres variables. J’ai aussi appris à identifier l’importance de la condition d’arrêt pour éviter les appels infinis, et à simplifier le code en supprimant les variables intermédiaires inutiles.