Vanilla-Js
Javascript-Natif
Quiz-Vanilla-Js-Senior
Web-Workers
Proxy
Intersection-Observer
Mutationobserver
Requestanimationframe
Debounce
Throttle
Generators
Weakmap
Questions-Entretien-Vanilla-Js-Senior
Qcm-Vanilla-Js-Avance
📝
Entretien Vanilla JS Senior — Performance et Web APIs
20 questions Vanilla JS niveau senior : Web Workers, Proxy, MutationObserver, IntersectionObserver, requestAnimationFrame, generators, WeakMap, debounce/throttle et patterns avancés. Pour réussir un entretien Senior JS natif.
Banque de révision : les 30 questions corrigées
Voici l'intégralité des 30 questions de « Entretien Vanilla JS Senior — Performance et Web APIs », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.
Explication :
Web Workers s'executent dans un thread separe, sans acces au DOM. Communication via postMessage(). Utile pour les calculs lourds (compression, crypto, parsers) qui bloqueraient sinon le thread principal.
Web Worker = thread separe | postMessage = communication avec le main thread
Explication :
requestAnimationFrame(fn) appelle fn avant que le navigateur ne redessine l'ecran (~60fps). Contrairement a setInterval, il s'adapte au framerate, economise la batterie si l'onglet est inactif et evite les sautes.
rAF = synchronise avec le repaint | ideal pour les animations JS fluides
Explication :
Proxy(target, handler) permet d'intercepter les operations : get, set, has, deleteProperty, apply, construct, etc. Utile pour la validation de donnees, la journalisation, les objets reactifs (Vue 3 l'utilise en interne).
Proxy = intercepteur d'operations sur objet (get/set/delete...)
Explication :
MutationObserver observe de facon asynchrone les changements DOM. On configure ce qu'on observe : childList (enfants), attributes, characterData, subtree. Remplace les anciens Mutation Events depreciees.
MutationObserver = React au changement DOM | observe({childList: true, subtree: true})
Explication :
Symbol() cree une valeur primitive unique. Symbol("desc") !== Symbol("desc"). Utilise pour des cles de proprietes privees ou pour implenter des protocoles comme [Symbol.iterator]. Jamais enumere par for...in.
Symbol() = toujours unique | [Symbol.iterator] = protocole iterable
Explication :
function* retourne un generateur (iterateur). Chaque appel a next() execute jusqu'au prochain yield. Le generateur retourne {value: yieldedValue, done: false} jusqu'a la fin, puis {value: undefined, done: true}.
function* + yield = generateur | next() = {value, done}
Explication :
WeakMap accepte uniquement des objets comme cles. Ces references sont faibles : si l'objet n'a plus d'autres references, il peut etre garbage collecte. WeakMap n'est pas enumerable ni iterable.
WeakMap = cles objets uniquement, references faibles, pas iterable
Explication :
customElements.define(name, constructor) enregistre un element personnalise. Le nom doit contenir un tiret (my-component). La classe etend HTMLElement et peut implementer connectedCallback, disconnectedCallback, attributeChangedCallback.
customElements.define() + classe extends HTMLElement = Web Component
Explication :
Le Revealing Module Pattern utilise une IIFE qui retourne un objet exposant uniquement les API publiques. Les variables internes sont privees par closure. Precede les modules ES6 natifs.
Revealing Module = IIFE + closure + objet retourne avec API publique
Explication :
Object.freeze() rend un objet immutable en surface (shallow). Les proprietes ne peuvent plus etre modifiees, ajoutees ou supprimees. En mode strict, toute tentative lance une TypeError. Pour une immutabilite profonde, il faut recursivement freeze.
freeze = immutable en surface | deep freeze = appel recursif
Explication :
Le debounce attend que les appels s'arretent avant d'executer. Ex: debounce(search, 300) attend 300ms d'inactivite avant de lancer la recherche. Ideal pour la saisie utilisateur (input, resize).
Debounce = attend la fin des appels | Throttle = limite la frequence
Explication :
Debounce : si vous tapez continument, la fonction attend que vous arrietiez. Throttle : la fonction s'execute au maximum une fois par intervalle meme si vous continuez. Throttle = scroll, debounce = recherche.
Debounce = fin d'activite | Throttle = cadence reguliere maximale
Explication :
performance.now() retourne un DOMHighResTimeStamp avec une precision sous-milliseconde. Contrairement a Date.now(), il n'est pas affecte par les ajustements d'horloge systeme. Ideal pour mesurer des durees precises.
performance.now() = haute precision | Date.now() = timestamp Unix en ms
Explication :
structuredClone() cree une copie profonde via l'algorithme de clonage structure. Supporte : objets, tableaux, Map, Set, Date, RegExp, ArrayBuffer, etc. Ne supporte pas les fonctions ni les noeuds DOM.
structuredClone() = deep clone natif (plus simple que JSON.parse/stringify)
Explication :
async function* combine generateur et async. Chaque yield peut etre une promesse. On itere avec for await...of. Utile pour consommer des flux de donnees paginates ou des streams API.
async function* + yield + for await...of = flux de donnees asynchrones
Explication :
On cree un IntersectionObserver, on passe une callback qui recoit les entries, on filtre isIntersecting, on charge l'image (data-src -> src), puis on appelle unobserve(). Plus performant que les evenements scroll.
new IntersectionObserver(cb).observe(el) | isIntersecting pour declencher
Explication :
L'IIFE (() => { ... })() cree une portee isolee. Les variables internes ne polluent pas le scope global. Tres utilise avant les modules ES6 pour l'encapsulation. Encore utile pour initialiser du code sans polluer.
IIFE = (() => { code })() : portee isolee, execution immediate
Explication :
Reflect.apply(fn, ctx, args) est equivalent a fn.apply(ctx, args) mais fait partie de l'API Reflect qui correspond 1:1 aux traps Proxy. Utile dans les handlers Proxy pour appeler le comportement par defaut.
Reflect.apply() = Function.apply() mais via l'API Reflect standard
Explication :
Le Shadow DOM cree un arbre DOM encapsule : les styles CSS n'en sortent pas et les styles externes n'y entrent pas. On l'attache avec element.attachShadow({mode: "open"}). Base des Web Components natifs.
Shadow DOM = encapsulation CSS + DOM | base des Web Components
Explication :
Retourne un objet avec : value (valeur), writable (modifiable), enumerable (visible dans for...in), configurable (peut etre supprimee/modifiee). Les proprietes non-writable sont lues seules. Utile pour le metaprogramming.
Descripteur = value + writable + enumerable + configurable
Explication :
removeEventListener necessite la meme reference de fonction qu'addEventListener. Les fonctions anonymes ne peuvent pas etre supprimees. WeakRef permet aussi des references faibles vers des objets handler pour eviter les retentions.
Fuite memoire = listener non supprime | stocker la reference + removeEventListener
Explication :
Le pattern Observer (pub/sub) maintient une liste de subscribers. emit() appelle toutes les callbacks. subscribe() ajoute une callback, unsubscribe() la retire. Base de nombreux systemes de gestion d'etat.
Observer = subscribe/emit/unsubscribe | base des stores reactifs
Explication :
Les microtaches (Promise.then, queueMicrotask, MutationObserver) s'executent apres le code courant mais avant les macrotaches (setTimeout, setInterval). queueMicrotask() est plus explicite et semantique qu'une promesse resolue.
Ordre : code sync -> microtaches -> macrotaches | queueMicrotask = priorite haute
Explication :
Un objet est iterable s'il a une methode [Symbol.iterator]() retournant un iterateur. L'iterateur a une methode next() qui retourne {value: any, done: boolean}. Permet d'utiliser for...of, spread, destructuration.
[Symbol.iterator]() + next() = protocole iterable personnalise
Explication :
La memoization cache les resultats en fonction des arguments. Ex: memo.get(arg) || (result = fn(arg), memo.set(arg, result), result). Ideal pour les fonctions pures couteuses (fibonacci, calculs, parsers).
Memoization = cache des resultats par arguments (Map ou WeakMap)
Explication :
[1,[2,[3]]].flat() = [1,2,[3]]. flat(Infinity) aplatit entierement. flatMap(fn) combine map() puis flat(1). Utile pour normaliser des donnees arborescentes ou les resultats de plusieurs fetch.
flat() = aplati 1 niveau | flat(Infinity) = aplati tout | flatMap = map + flat
Explication :
tag`Hello ${name}` appelle tag(strings, ...values). La fonction tag recoit les parties statiques (strings[]) et les valeurs interpolees. Utilise par styled-components, GraphQL (gql), sql, html templates securises.
Tagged template = fonction devant le backtick | intercepte l'interpolation
Explication :
Avec les modules ES6, le singleton est naturel : la valeur exportee est mise en cache. Avec une closure : let instance; function getInstance(){ return instance || (instance = new MyClass()); }. static getInstance() est aussi valide.
Singleton = une instance unique | module ES6 = singleton naturel
Explication :
flatMap(fn) = map(fn).flat(1). Ex: ["hello world"].flatMap(s => s.split(" ")) = ["hello", "world"]. Plus performant que les deux appels separes. Utile pour transformer des tableaux en aplatissant les resultats.
flatMap = map + flat niveau 1 | ["a b"].flatMap(s => s.split(" ")) = ["a","b"]
Explication :
compose(f, g, h)(x) = f(g(h(x))). Implementation : const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x). pipe() va dans l'autre sens : fns.reduce(). Base de la programmation fonctionnelle.
compose = reduceRight | pipe = reduce | f(g(h(x))) = composition de droite a gauche