Quiz : Maîtrise avancée des erreurs JavaScript
Vos exceptions sont-elles vraiment exceptionnelles ?
Vous pensez maîtriser les erreurs JavaScript sur le bout des doigts ?
- Mettez à l’épreuve votre expertise en gestion d’erreurs ! 💥
- Aucun compte requis. ✨
- Choix multiples. 🤖 … Ce ne sont pas les questions try‑catch habituelles !
Que renvoie JSON.stringify(error) ?
const error = new Error('Oops');console.log(JSON.stringify(error));Les objets Error possèdent des propriétés non‑énumérables (message, name, stack), donc JSON.stringify() renvoie {}. C’est un piège fréquent lorsqu’on envoie des erreurs dans les réponses d’API. Utilisez JSON.stringify(error, Object.getOwnPropertyNames(error)) ou créez un objet simple à la place.
Pensez aux propriétés énumérables des objets Error.
Quelle est la différence entre ces deux ?
const err = new Error('Test');console.log(err);console.log(JSON.stringify(err));console.log(err) affiche l’erreur avec son message et sa trace de pile parce que la console a un traitement spécial pour les objets Error. JSON.stringify(err) renvoie '{}' parce que les propriétés de Error ne sont pas énumérables. Cette différence piège de nombreux développeurs qui déboguent des API.
Comparez le traitement des objets par console.log et par la sérialisation JSON.
Quels sont les résultats de ces vérifications ?
class CustomError extends Error {}const err = new CustomError('test');
console.log(err instanceof CustomError);console.log(err instanceof Error);console.log(err instanceof Object);Les trois renvoient true. CustomError hérite de Error, qui hérite de Object. L’opérateur instanceof parcourt toute la chaîne de prototypes, donc une instance de CustomError est aussi une instance de Error et de Object.
Rappelez-vous la chaîne de prototypes dans l’héritage JavaScript.
Supposez que iframeError a été créé dans une iframe de même origine, puis transmis à la fenêtre parente.
console.log(iframeError instanceof Error);Les contextes d’exécution ont des constructeurs Error distincts : ce test peut donc renvoyer false. Object.prototype.toString.call(obj) reconnaît des erreurs ordinaires issues d’un autre contexte, mais Symbol.toStringTag permet d’imiter son résultat. Ce n’est pas une preuve d’authenticité.
Les contextes d’exécution ont des constructeurs Error distincts.
Que se passe-t-il lorsqu’on lève une exception avec une chaîne ?
try { throw "Oops!";} catch (e) { console.log(e instanceof Error); console.log(typeof e);}JavaScript autorise le lancer de n’importe quelle valeur. Ici, e instanceof Error vaut false et typeof e est "string". Cela peut casser le code de gestion des erreurs qui suppose que toutes les exceptions capturées sont des objets Error. Lancez toujours des instances d’Error pour faciliter le débogage.
JavaScript permet de lever n’importe quelle valeur, pas seulement un objet Error.
Quelle est la valeur de err.name ?
class CustomError extends Error { constructor(message) { super(message); this.name = this.constructor.name; }}const err = new CustomError('test');console.log(err.name);err.name est "CustomError" parce que this.constructor.name renvoie le nom de la classe. Affecter this.name = this.constructor.name est un schéma courant pour garantir que les classes d’erreur personnalisées affichent le bon nom dans les traces de pile et les messages d’erreur.
Examinez la valeur de this.constructor.name.
Quel est le résultat sans définir name ?
class MyError extends Error { // No constructor or name setting}const err = new MyError('test');console.log(err.name);Sans définir explicitement this.name, l’erreur hérite de la propriété name par défaut de la classe Error, qui est "Error". C’est pourquoi les classes d’erreur personnalisées doivent toujours définir this.name = this.constructor.name dans leur constructeur.
Quelle est la valeur par défaut de la propriété name d’Error ?
Que renvoie wrapper.cause.message ?
const original = new Error('Original error');const wrapper = new Error('Wrapper', { cause: original });console.log(wrapper.cause.message);Error.cause (ES2022) permet de chaîner les erreurs pour conserver le contexte de l’erreur originale. wrapper.cause fait référence à l’erreur originale, donc wrapper.cause.message renvoie "Original error". C’est utile pour envelopper des erreurs de bas niveau avec un contexte de niveau supérieur.
Error.cause permet de chaîner les erreurs en JavaScript moderne.
On utilise ici V8/Node.js, où Error.captureStackTrace est disponible.
Que fait Error.captureStackTrace ?
function createError(msg) { const err = new Error(msg); Error.captureStackTrace(err, createError); return err;}const error = createError('test');Error.captureStackTrace (V8/Node.js) supprime la fonction spécifiée (createError) de la trace de pile, rendant les fonctions usine d’erreur invisibles aux utilisateurs finaux. Cela crée des traces de pile plus propres qui pointent vers l’endroit où l’usine a été appelée, pas vers l’usine elle‑même.
Cette fonctionnalité de V8 permet de simplifier les traces de pile.
Quel est le message d’erreur ?
function validate(value) { if (!value) { throw new Error( `Value ${value} is invalid` ); }}try { validate(undefined);} catch (e) { console.log(e.message);}Les littéraux de modèle convertissent undefined en la chaîne "undefined" lors de l’interpolation. Le message d’erreur devient "Value undefined is invalid". Pour des messages plus propres, envisagez d’utiliser value ?? 'null' ou des vérifications similaires avant l’interpolation.
Comment l’interpolation des littéraux de modèle traite-t-elle undefined ?
Qu’est‑ce qui est envoyé au client ?
// Express.js routeapp.get('/api/data', (req, res) => { const error = new Error('Database failed'); res.json({ error });});res.json() utilise JSON.stringify() en interne, donc l’objet Error devient {}. Le client reçoit {"error":{}}. Pour corriger cela, utilisez res.json({ error: error.message }) ou res.json({ error: { message: error.message, name: error.name } }).
Rappelez-vous comment JSON.stringify sérialise les objets Error.
Que peut accepter Promise.reject() ?
Promise.reject('string').catch(e => console.log(typeof e));Promise.reject({code: 404}).catch(e => console.log(e.code));Promise.reject(42).catch(e => console.log(e));Comme throw, Promise.reject() accepte n’importe quelle valeur – chaînes, objets, nombres, etc. Cela affiche "string", 404 et 42. Vérifiez toujours le type des valeurs attrapées dans les chaînes de promesses, surtout lorsqu’un code tiers peut rejeter des valeurs qui ne sont pas des objets Error.
Les rejets de promesses ressemblent aux exceptions levées par throw.
À quel point error.code et error.errno sont-ils fiables ?
const fs = require('fs');fs.readFile('missing.txt', (err, data) => { if (err) { console.log(err.code); // 'ENOENT' console.log(err.errno); // -2 }});Des propriétés comme code et errno sont spécifiques à l’environnement (Node.js dans ce cas) et ne font pas partie de l’objet Error standard. Les erreurs du navigateur n’auront pas ces propriétés. Vérifiez toujours leur existence : if (err.code === 'ENOENT') plutôt que de supposer qu’elles existent.
Pensez aux différents environnements JavaScript et types d’erreurs.
Que renvoient ces vérifications ?
const fakeError = { name: 'Error', message: 'Fake error', stack: 'fake stack'};
console.log(fakeError instanceof Error);console.log(Object.prototype.toString.call( fakeError) === '[object Error]');Les deux comparaisons valent false pour cet objet précis. Son prototype n’est pas Error.prototype et son étiquette par défaut est [object Object]. Toutefois, ajouter [Symbol.toStringTag]: "Error" rendrait la deuxième comparaison vraie. Une étiquette ou des propriétés ressemblant à celles d’une erreur ne prouvent pas son authenticité.
Le premier test examine la chaîne de prototypes. Le second produit une étiquette de type qui peut être influencée par Symbol.toStringTag.
Maîtriser l’art de la gestion des erreurs
Des pièges de sérialisation aux échecs d’instanceof entre contextes, ces notions avancées distinguent les développeurs juniors des professionnels expérimentés endommagés.
Prêt pour de nouveaux défis ? Consultez notre collection complète de quiz pour d’autres casse‑têtes sur JavaScript, les algorithmes et bien plus.
