Questions d'entretien JavaScript
Les entretiens JavaScript testent votre compréhension des mécanismes fondamentaux du langage — portée, closures, comportement asynchrone et chaîne de prototypes — souvent avec de courts exercices de codage.
Ce que couvrent les entretiens JavaScript
Portée et closures
Portée lexicale, closures, hoisting et zone morte temporelle.
Async et boucle d'événements
Callbacks, promesses, async/await, microtasks vs macrotasks.
this et prototypes
Comment this est lié, call/apply/bind et héritage prototypal.
Types et coercition
== vs ===, truthiness et pièges courants de coercition.
Exemples de questions d'entretien JavaScript
- Qu'est-ce qu'une closure et donnez un exemple d'utilisation pratique.Ce qu'une bonne réponse couvre
- Fermeture lexicale
- Variables capturées
- Module pattern
- Gestion des événements
- Mémoire et garbage collection
Voir un exemple de réponse
Une closure est une fonction qui se souvient de l'environnement lexical dans lequel elle a été créée, même après que cet environnement a cessé d'exister. Par exemple, une fonction interne retournée par une fonction externe conserve l'accès aux variables de la fonction externe. Un usage pratique courant est le module pattern, où l'on crée des variables privées en utilisant une IIFE (Immediately Invoked Function Expression) qui expose seulement certaines méthodes. Par exemple : const compteur = (() => { let count = 0; return { increment: () => count++, getCount: () => count }; })(); Les closures sont également utiles dans les callbacks asynchrones ou les gestionnaires d'événements pour conserver des données contextuelles. Il faut cependant faire attention aux fuites mémoire si des références persistent inutilement, car la closure empêche le garbage collection des variables capturées.
- Expliquez la boucle d'événements, les microtasks et les macrotasks.Ce qu'une bonne réponse couvre
- Call stack
- Microtask queue (Promise, MutationObserver)
- Macrotask queue (setTimeout, DOM events)
- Priorité d'exécution
- Boucle d'événements JavaScript
Voir un exemple de réponse
La boucle d'événements est le mécanisme qui permet à JavaScript d'être asynchrone malgré son modèle mono-thread. Le call stack exécute le code synchrone. Lorsque des opérations asynchrones sont rencontrées, leurs callbacks sont placés dans des files d'attente. Les microtasks (par exemple, les résolutions de promesses via .then(), queueMicrotask) sont traitées immédiatement après la fin de la tâche courante du call stack, avant le rendu et avant les macrotasks. Les macrotasks (setTimeout, setInterval, I/O) sont exécutées lors du prochain cycle. Ainsi, l'ordre est : synchrone → microtasks (jusqu'à épuisement) → macrotask (une par cycle). Un piège classique est de créer une boucle infinie de microtasks, ce qui bloque le rendu. Par exemple, setTimeout(() => {}, 0) est une macrotask, tandis que Promise.resolve().then(...) est une microtask et sera exécutée avant le prochain setTimeout.
- Quelle est la différence entre == et ===, et quand == est-il acceptable ?Ce qu'une bonne réponse couvre
- Opérateur d'égalité stricte (===)
- Opérateur d'égalité abstraite (==)
- Coercition de type
- Cas acceptable : null/undefined
- Préférence générale pour ===
Voir un exemple de réponse
L'opérateur == (égalité abstraite) compare deux valeurs après avoir effectué une coercition de type, tandis que === (égalité stricte) compare sans conversion. Par exemple, 1 == '1' donne true, mais 1 === '1' donne false. L'utilisation de == est généralement déconseillée car elle peut mener à des résultats surprenants, comme 0 == false ou '' == false. Cependant, il est acceptable d'utiliser == pour vérifier si une valeur est null ou undefined de manière concise, car null == undefined est le seul cas où deux valeurs différentes sont considérées égales sans effet de bord. Dans tous les autres cas, il est préférable d'utiliser === pour éviter des bugs subtils liés à la coercition implicite.
- Comment `this` est-il déterminé et comment call/apply/bind le modifient-ils ?Ce qu'une bonne réponse couvre
- Règle de liaison par défaut (window/global)
- Implicite (objet appelant)
- Explicite (call, apply, bind)
- Arrow functions (lexical this)
- new binding
Voir un exemple de réponse
La valeur de `this` est déterminée par la manière dont une fonction est appelée. En mode non strict, si la fonction est appelée sans contexte, `this` est l'objet global (window). En mode strict, il est undefined. Lorsqu'une fonction est appelée comme méthode d'un objet, `this` fait référence à cet objet. Avec `call` et `apply`, vous passez explicitement la valeur de `this` et invoquez immédiatement la fonction. `bind` retourne une nouvelle fonction avec `this` lié en permanence. Les fonctions fléchées ne possèdent pas leur propre `this` ; elles héritent du `this` de leur contexte lexical englobant. Le mot-clé `new` crée un nouvel objet et lie `this` à ce dernier. Un piège courant est de perdre le `this` dans un callback ; on utilise souvent bind ou une fonction fléchée pour le conserver.
- Implémentez une fonction debounce (ou throttle).Ce qu'une bonne réponse couvre
- clearTimeout pour annuler
- Fermeture pour conserver le timer
- Arguments et contexte (apply)
- Complexité temporelle O(1) par appel
- Option immediate (déclenchement immédiat)
Voir un exemple de réponse
Voici une implémentation complète de debounce en JavaScript. La fonction `debounce` prend une fonction `func` et un délai `delay` en millisecondes. Elle retourne une nouvelle fonction qui diffère l'appel de `func` jusqu'à ce qu'il n'y ait plus eu d'appel pendant `delay` ms. On utilise `clearTimeout` pour annuler le timer précédent et `setTimeout` pour en créer un nouveau. On préserve `this` et les arguments avec `apply`. La complexité temporelle de l'appel au debounce est O(1), mais l'exécution réelle est décalée. Une variante courante inclut une option `immediate` pour exécuter la fonction tout de suite puis ignorer les appels successifs.
Solution de référencejavascript // Retourne une fonction debouncée avec option immediate function debounce(func, delay, immediate = false) { let timeoutId; // variable pour stocker le timer return function(...args) { const context = this; // sauvegarde du contexte // Fonction à exécuter après le délai const later = function() { timeoutId = null; if (!immediate) func.apply(context, args); }; // Si immediate est vrai et qu'aucun timer n'est en cours => exécute immédiatement const callNow = immediate && !timeoutId; clearTimeout(timeoutId); // annule le timer précédent timeoutId = setTimeout(later, delay); // démarre un nouveau timer if (callNow) func.apply(context, args); }; } // Exemple d'utilisation : const logger = debounce(console.log, 300); logger('a'); // ne se déclenchera pas tout de suite setTimeout(() => logger('b'), 200); // 'b' est ignoré car le timer est réinitialisé setTimeout(() => logger('c'), 400); // 'c' s'affiche après 300ms de silence - Quelle est la différence entre var, let et const ?Ce qu'une bonne réponse couvre
- Portée fonctionnelle vs bloc
- Hoisting (var avec undefined, let/const en TDZ)
- Réaffectation (var/let oui, const non)
- Redéclaration (var autorisée, let/const non)
- Const sur les objets (propriétés mutables)
Voir un exemple de réponse
Les différences principales entre var, let et const concernent la portée, le hoisting et la mutabilité. var a une portée fonctionnelle et est hoisted avec une valeur undefined, ce qui signifie qu'on peut l'utiliser avant sa déclaration (sans erreur mais avec undefined). let et const ont une portée de bloc et sont hoisted mais placées dans une zone morte temporelle (temporal dead zone) : les utiliser avant la déclaration provoque une ReferenceError. var permet la redéclaration dans le même scope, tandis que let et const la refusent. const empêche la réaffectation de la variable (l'identifiant ne peut pas changer de valeur), mais si la valeur est un objet, ses propriétés restent modifiables. On recommande d'utiliser const par défaut, et let lorsque la variable doit être réaffectée. var est à éviter dans le code moderne pour limiter les bugs de portée.
Comment se préparer
- Soyez capable de prédire la sortie d'extraits piégeux (closures dans des boucles, ordre asynchrone).
- Entraînez-vous à implémenter debounce, throttle et une promesse simple à partir de zéro.
- Comprenez suffisamment la boucle d'événements pour expliquer précisément l'ordre asynchrone.
- Connaissez les fonctionnalités modernes (let/const, fonctions fléchées, déstructuration, modules) et pourquoi elles existent.
Questions fréquemment posées
JavaScript est-il encore demandé séparément de React ?
Oui — de nombreux entretiens incluent une session purement JavaScript sur les closures, l'async et `this`, indépendamment de tout framework.
Dois-je connaître TypeScript ?
De plus en plus oui pour les postes frontend, mais les mécanismes fondamentaux de JavaScript restent la base testée par les recruteurs.
Quels sujets JavaScript reviennent le plus ?
Les closures, la boucle d'événements et les promesses, la liaison de `this`, et l'implémentation d'utilitaires comme debounce ou throttle.
Comment puis-je m'entraîner aux entretiens JavaScript ?
Prédisez la sortie d'extraits et implémentez de petits utilitaires sous pression de temps. Offersly peut générer des questions JavaScript adaptées à votre CV.
Pratiquez les questions JavaScript avec des retours instantanés de l'IA
Téléchargez votre CV, obtenez un entretien simulé personnalisé et voyez exactement ce qu'il faut améliorer — gratuit pour commencer.