🟨
Senior 25 questions JavaScript

Questions JavaScript Senior

25 questions avancees JavaScript/TypeScript pour les profils seniors. Patterns avances, performance, securite et architecture.

1. Expliquez le fonctionnement de l'event loop en JavaScript.

L'event loop est le mecanisme qui permet a JavaScript (single-threaded) de gerer l'asynchrone. Le moteur execute le code synchrone dans la call stack. Les operations asynchrones (setTimeout, fetch, I/O) sont deleguees aux Web APIs du navigateur (ou libuv dans Node.js). Une fois terminees, leurs callbacks sont places dans la task queue (macrotasks). Les Promises et les MutationObserver utilisent la microtask queue, traitee prioritairement. Cycle : 1) Executer la call stack, 2) Vider la microtask queue, 3) Executer une macrotask, 4) Repeter. Les microtasks sont toujours traitees avant la prochaine macrotask. Comprendre cette priorite explique pourquoi Promise.resolve().then() s'execute avant setTimeout(fn, 0).

2. Comment fonctionne le systeme de prototypes en JavaScript ?

Chaque objet JavaScript a un prototype interne ([[Prototype]]). Quand on accede a une propriete, le moteur cherche d'abord sur l'objet, puis remonte la chaine de prototypes jusqu'a Object.prototype (puis null). Les classes ES6 sont du sucre syntaxique sur les prototypes. Object.create(proto) cree un objet avec le prototype specifie. Object.getPrototypeOf(obj) retourne le prototype. Le prototype pattern : les methodes partagees sont sur le prototype (une seule copie en memoire), les proprietes d'instance sur l'objet. Attention : modifier un prototype affecte tous les objets qui en heritent. Les proprietes propres masquent les proprietes du prototype (shadowing). hasOwnProperty distingue les proprietes propres des heritees.

3. Expliquez les closures et leurs cas d'utilisation avances.

Une closure est une fonction qui capture les variables de son scope englobant, meme apres que ce scope a termine son execution. Le mecanisme : la fonction garde une reference au lexical environment de sa creation. Cas d'utilisation : encapsulation (simuler les variables privees avec un IIFE ou un module), factories (fonction retournant des fonctions configurees), currying (f(a)(b)(c) au lieu de f(a,b,c)), memoization (cache dans la closure), event handlers (capturer des variables dans les callbacks). Piege classique : la boucle for avec var (toutes les closures partagent la meme variable). Solution : let (block-scoped) ou IIFE. Les closures gardent des references, pas des copies, ce qui peut causer des fuites memoire si les objets references sont volumineux.

4. Qu'est-ce que les Proxies et Reflect en JavaScript ?

Le Proxy intercepte les operations fondamentales sur un objet (lecture, ecriture, appel de fonction, etc.) via des traps. Syntaxe : new Proxy(target, handler). Traps courantes : get (lecture de propriete), set (ecriture), has (operateur in), deleteProperty (delete), apply (appel de fonction), construct (new). Reflect fournit les methodes correspondantes aux traps avec le comportement par defaut. Cas d'utilisation : validation (verifier les types a l'ecriture), observation/reactivite (Vue 3 utilise Proxy pour la reactivite), logging (tracer les acces), valeurs par defaut (retourner une valeur si la propriete n'existe pas), revocable proxies pour le controle d'acces temporaire.

5. Comment gerer la concurrence et le parallelisme en JavaScript ?

JavaScript est single-threaded mais gere la concurrence via l'event loop et les callbacks/promises. Web Workers : threads separes pour les taches CPU-intensives, communication par messages (postMessage), pas d'acces au DOM. SharedArrayBuffer + Atomics : memoire partagee entre workers avec operations atomiques pour la synchronisation. Promise.all : parallelise des operations asynchrones independantes. Promise.allSettled : attend toutes les promises meme si certaines rejettent. Promise.race : retourne la premiere promise resolue. AbortController : annuler des operations asynchrones (fetch, event listeners). Structured concurrency : pattern ou les taches enfants sont liees au cycle de vie du parent. En Node.js, les worker_threads pour le parallelisme CPU.

6. Expliquez les WeakMap, WeakSet et WeakRef.

WeakMap : map dont les cles sont des references faibles vers des objets. Si l'objet cle n'a plus d'autres references, il est garbage collected (et l'entree disparait). Les cles ne sont pas iterables. Cas d'utilisation : metadata privee sur des objets sans empecher leur GC, caching lie a la duree de vie d'un objet, DOM metadata (associer des donnees a des elements sans fuite memoire). WeakSet : ensemble d'objets avec des references faibles (marquer des objets comme "vus"). WeakRef : reference faible explicite vers un objet, deref() retourne l'objet ou undefined s'il a ete GC. FinalizationRegistry : callback quand un objet est garbage collected. Ces structures sont essentielles pour eviter les fuites memoire dans les applications longue duree.

7. Comment fonctionne le module system en JavaScript moderne ?

ES Modules (ESM) : standard officiel. import/export, statique (analysable au build pour tree-shaking), asynchrone, strict mode par defaut. CommonJS (CJS) : historique Node.js, require/module.exports, synchrone, dynamique. Dynamic import : import() retourne une Promise, utile pour le code splitting et le lazy loading. Import maps : mapping des specifiers aux URLs dans le navigateur (sans bundler). Tree-shaking : elimination du code mort, possible grace aux imports statiques ESM. Les bundlers (Webpack, Vite, esbuild) resolvent les modules et optimisent le bundle. Top-level await : await directement dans un module ESM (pas besoin de wrapper async). Le pattern barrel (index.js re-exportant tout) peut nuire au tree-shaking si mal utilise.

8. Quels sont les patterns de programmation fonctionnelle en JavaScript ?

Fonctions pures : meme entree donne toujours la meme sortie, pas d'effets de bord. Immutabilite : ne pas modifier les donnees, creer de nouvelles copies (spread operator, Object.freeze, Immer). Higher-order functions : fonctions qui prennent ou retournent des fonctions (map, filter, reduce). Composition : combiner des fonctions simples en fonctions complexes (pipe/compose). Currying : transformer f(a,b) en f(a)(b) pour l'application partielle. Functors : conteneurs mappable (Array.map, Promise.then). Monades : chainer des operations avec gestion du contexte (Promise est monadique). En pratique : preferer la transformation de donnees aux mutations, utiliser les methodes d'array fonctionnelles, eviter les boucles imperatives. Bibliotheques : Ramda, fp-ts pour le TypeScript.

9. Comment optimiser les performances JavaScript dans le navigateur ?

Critical rendering path : minimiser le JS bloquant le rendu, defer/async pour les scripts. Code splitting : charger le JS necessaire a la page courante, lazy load le reste. Tree-shaking : eliminer le code mort au build. Web Workers : deplacer les calculs lourds hors du main thread. requestAnimationFrame : synchroniser les animations avec le rafraichissement ecran. Debounce/throttle : limiter la frequence d'execution des handlers d'evenements. Virtualisation : ne rendre que les elements visibles dans les listes longues. Memory management : eviter les fuites (event listeners non supprimes, closures retenant des objets, timers oublies). Performance API : mesurer avec performance.mark/measure. Lighthouse et les Core Web Vitals (LCP, FID, CLS) pour le monitoring.

10. Expliquez les generators et les iterators en JavaScript.

Les iterators implementent le protocole d'iteration : un objet avec une methode next() retournant { value, done }. Le protocole iterable : un objet avec Symbol.iterator retournant un iterator. Les structures iterables : Array, String, Map, Set, arguments. Les generators (function*) simplifient la creation d'iterators. yield suspend l'execution et retourne une valeur. yield* delegue a un autre generator. Cas d'utilisation : generation de sequences infinies (Fibonacci), iteration paresseuse (lazy evaluation), flux de controle asynchrone (avec yield et promises, precurseur d'async/await), pipelines de transformation de donnees. La boucle for...of et le spread operator consomment les iterables. Async generators (async function*) combinent generators et async pour les flux de donnees asynchrones (lecture de fichier ligne par ligne).

Besoin d'aide pour preparer vos entretiens ?

Decrivez votre profil pour des conseils de preparation personnalises.

Recevoir des conseils

Questions frequentes

Quel framework JS maitriser en 2026 ?
React reste dominant, mais Next.js, Astro et Svelte gagnent du terrain. La polyvalence est un atout.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.