JavaScript 124 termes

124 termes affichés

TypeBestPractice Concept DataStructure Method Pattern Principle Security Tool
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Mis à jour ces 90 derniers jours 24 nouvelles · 29 révisées

AbortController

JavaScript 🟡 Mid

API pour annuler des opérations asynchrones (fetch, event listeners, streams). Créé un signal qui peut être passe a n'importe quelle API supportant l'annulation.

Un bouton d'arrêt d'urgence : tu peux stopper une opération en cours a tout moment.

const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
  .catch(err => {
    if (err.name === 'AbortError') console.log('Annule');
  });
// Annuler apres 5s
setTimeout(() => controller.abort(), 5000);

Cas d'usage : Timeout de requêtes fetch, annulation lors du démontage d'un composant React, cleanup de listeners.

Anti-pattern : Ne jamais annuler les fetch dans les useEffect React, provoquant des memory leaks.
#core#async#navigateur

Array Methods

JavaScript 🟢 Junior? entretien

Méthodes fonctionnelles : map (transformer), filter (filtrer), reduce (accumuler), find/findIndex (chercher), some/every (tester), flat/flatMap (aplatir). Chainables et non-mutantes.

Un pipeline de cuisine : laver (filter), couper (map), mixer (reduce) — chaque étape transforme sans toucher au stock original.

const result = users
  .filter(u => u.active)
  .map(u => u.name)
  .sort();
const total = prices.reduce((sum, p) => sum + p, 0);
const found = items.find(i => i.id === 42);

Cas d'usage : Transformation de données, filtrage de listes, calculs d'aggregation, recherche.

Anti-pattern : Utiliser forEach pour construire un nouveau tableau au lieu de map.
#core#fondamental#interview

Array.fromAsync()

JavaScript 🟡 Mid

Méthode statique (Stage 4, listée par TC39 pour ES2026) qui construit un tableau à partir d'un itérable asynchrone, d'un itérable synchrone de promesses ou d'un objet array-like, et renvoie une promesse du tableau. Chaque valeur est attendue séquentiellement, à la différence de Promise.all qui lance tout en parallèle. Largement disponible dans les navigateurs depuis janvier 2024.

Ramasser les lettres d'une boîte au fil de leur arrivée, dans l'ordre, jusqu'à la dernière.

async function* pages() {
  for (let p = 1; p <= 3; p++) yield await fetchPage(p);
}
const tout = await Array.fromAsync(pages()); // [page1, page2, page3]

// Avec fonction de transformation (attendue elle aussi)
const tailles = await Array.fromAsync([1, 2, 3], async n => n * 2);
// Séquentiel : 5 promesses de 100 ms ≈ 500 ms (Promise.all ≈ 100 ms)

Cas d'usage : Collecter un flux paginé, un ReadableStream ou un curseur base de données en tableau.

Anti-pattern : L'utiliser pour paralléliser des appels indépendants : c'est séquentiel, Promise.all est fait pour ça.
#core#ES2026#async

ArrayBuffer

JavaScript 🔴 Senior

Zone de mémoire brute de taille fixe, non redimensionnable. Accessible via des TypedArrays (Uint8Array, Float32Array, etc.) ou DataView pour lire/écrire des données binaires.

Un terrain vague clôture : il existe en mémoire, mais tu as besoin d'outils (TypedArray) pour y construire quelque chose.

const buf = new ArrayBuffer(16);
const view = new Uint8Array(buf);
view[0] = 255;
const float = new Float32Array(buf);
// Meme memoire, vue differente

Cas d'usage : Traitement d'images, audio, fichiers binaires, communication avec WebGL ou WASM.

#core#avance#performance

Arrow Function

JavaScript 🟢 Junior

Syntaxe compacte pour les fonctions anonymes avec =>, qui ne possède ni son propre this, ni arguments, ni super. Le this est hérité du scope lexical englobant.

Un assistant qui n'a pas de bureau propre (pas de this) : il utilise toujours le bureau de son chef (scope parent).

const add = (a, b) => a + b;
const greet = name => `Hello ${name}`;
const getObj = () => ({ key: 'value' });

class Timer {
  start() {
    setInterval(() => console.log(this), 1000);
    // this = instance Timer (lexical)
  }
}

Cas d'usage : Callbacks, méthodes de tableaux (map, filter), quand on veut capturer le this du parent.

Anti-pattern : Utiliser une arrow function comme méthode d'objet literal : this ne pointe pas vers l'objet.
#core#ES6#fondamental

Async/Await

JavaScript 🟢 Junior? entretien

Sucre syntaxique sur les Promises. async déclaré une fonction retournant une Promise, await suspend l'exécution jusqu'a la résolution. Rend le code asynchrone lisible comme du synchrone.

Commander un café et attendre au comptoir : tu ne fais rien d'autre en attendant (await), mais le reste du café (event loop) continue de tourner.

async function fetchUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    return await res.json();
  } catch (err) {
    console.error('Fetch failed', err);
  }
}

Cas d'usage : Écrire du code asynchrone lisible pour les appels API, accès BD, opérations fichiers.

Anti-pattern : Oublier le try/catch autour d'un await, laissant les rejections non gérées crasher silencieusement.
#core#interview#async#fondamental

AsyncGenerator

JavaScript 🔴 Senior

Fonction async function* combinant générateurs et async/await. Peut yield des valeurs de manière asynchrone, consommable via for await...of.

Un chef qui prépare les plats un par un (yield) en attendant chaque ingrédient de la livraison (await).

async function* pollData(url, ms) {
  while (true) {
    const res = await fetch(url);
    yield await res.json();
    await new Promise(r => setTimeout(r, ms));
  }
}

Cas d'usage : Polling périodique, lecture de flux réseau, traitement de files de messages.

#core#async#avance

AsyncIterator

JavaScript 🔴 Senior

Protocole pour iterer sur des séquences asynchrones. L'objet implémenté [Symbol.asyncIterator]() et next() retourne une Promise de {value, done}. Utilisable avec for await...of.

Un podcast en streaming : chaque épisode arrive de manière asynchrone, et tu les écoutes un par un.

async function* fetchPages(url) {
  let page = 1;
  while (true) {
    const data = await fetch(`${url}?p=${page++}`);
    const json = await data.json();
    if (!json.length) return;
    yield json;
  }
}
for await (const page of fetchPages('/api')) {}

Cas d'usage : Pagination API, lecture de streams, traitement de données en flux.

#core#async#avance

Atomics

JavaScript 🔴 Senior

Objet global fournissant des opérations atomiques sur les SharedArrayBuffer : load, store, add, sub, and, or, xor, wait, notify. Garantit l'intégrité en contexte multithread.

Un tour de parole officiel : chaque personne attend son tour pour parler (wait/notify) et ses mots sont enregistres sans interruption (opérations atomiques).

const sab = new SharedArrayBuffer(4);
const arr = new Int32Array(sab);
Atomics.store(arr, 0, 42);
Atomics.load(arr, 0); // 42
Atomics.add(arr, 0, 8); // ancien: 42
Atomics.load(arr, 0); // 50

Cas d'usage : Synchronisation entre workers, compteurs partages, mutex software.

#core#avance#concurrence

Barrel Files

JavaScript 🟡 Mid

Fichier index.ts/js qui re-exporte les modules d'un dossier pour simplifier les imports. Peut nuire au tree shaking et au temps de build si mal utilise.

Un sommaire de livre : pratique pour trouver un chapitre, mais si le sommaire force a charger tout le livre, c'est contre-productif.

// components/index.ts (barrel)
export { Button } from './Button';
export { Modal } from './Modal';
export { Input } from './Input';

// Usage
import { Button } from './components';

Cas d'usage : API publiques de librairies, organisation de dossiers de composants.

Anti-pattern : Barrel files dans chaque sous-dossier qui forcent le bundler a parser des centaines de modules.
#core#modules#architecture

BigInt

JavaScript 🟡 Mid

Type primitif pour représenter des entiers de taille arbitraire, au-delà de Number.MAX_SAFE_INTEGER (2^53 - 1). Créé avec le suffixe n ou BigInt().

Un cahier avec un nombre illimité de pages pour écrire des nombres, contrairement a une calculatrice a écran fixe.

const big = 9007199254740993n;
big + 1n; // 9007199254740994n
// Attention : pas de melange
// big + 1; // TypeError
BigInt(Number.MAX_SAFE_INTEGER) + 1n;

Cas d'usage : Identifiants de bases de données 64-bit, calculs financiers de précision, cryptographie.

Anti-pattern : Mélanger BigInt et Number sans conversion explicite, provoquant un TypeError.
#core#ES2020

bind / call / apply

JavaScript 🟡 Mid? entretien

Méthodes de Function.prototype pour contrôler this. call(ctx, ...args) et apply(ctx, [args]) appellent immédiatement. bind(ctx, ...args) retourne une nouvelle fonction avec this lie.

call = téléphoner a quelqu'un maintenant. apply = idem mais tu lis la liste des courses. bind = enregistrer le numéro en favori pour appeler plus tard.

function greet(msg) { return `${msg}, ${this.name}`; }
const user = { name: 'Bob' };
greet.call(user, 'Hi');     // 'Hi, Bob'
greet.apply(user, ['Hi']);  // 'Hi, Bob'
const bound = greet.bind(user);
bound('Hey');               // 'Hey, Bob'

Cas d'usage : Fixer le this dans les callbacks, emprunter des méthodes d'un autre objet, partial application.

#core#interview

Biome

JavaScript 🟢 Junior

Formateur et linter unique en Rust pour JavaScript, TypeScript, JSX, JSON, CSS, GraphQL et HTML, successeur de Rome. Biome 2.4 (10 février 2026) a ajouté les extraits embarqués et l'accessibilité HTML ; Biome 2.5 (5 juin 2026) dépasse 500 règles, apporte des corrections automatiques dans les plugins GritQL et le lint inter-fichiers. Il propose un lint conscient des types sans dépendre de tsc.

Un seul artisan qui pose le carrelage et fait les joints, au lieu de deux corps de métier à coordonner.

# Installer, initialiser, vérifier
pnpm add -D @biomejs/biome
npx biome init          # crée biome.json
npx biome check --write . # formate + corrige le lint

# biome.json (extrait)
# { "formatter": { "indentStyle": "space" },
#   "linter": { "rules": { "recommended": true } } }

Cas d'usage : Remplacer Prettier + ESLint par un seul outil et une seule config, surtout sur des projets neufs.

Anti-pattern : Faire tourner Biome et Prettier en parallèle sur les mêmes fichiers : les deux se réécrivent l'un l'autre.
#tooling#lint#format#rust

Broadcast Channel

JavaScript 🟡 Mid

API de communication entre contextes de même origine (onglets, iframes, workers). Plus simple que SharedWorker pour du broadcast de messages.

Une radio interne d'entreprise : tous les bureaux (onglets) branchées sur la même fréquence reçoivent le message.

// Onglet 1
const bc = new BroadcastChannel('auth');
bc.postMessage({ type: 'logout' });
// Onglet 2
const bc2 = new BroadcastChannel('auth');
bc2.onmessage = (e) => {
  if (e.data.type === 'logout') redirectToLogin();
};

Cas d'usage : Synchroniser le logout entre onglets, mettre a jour le theme, notifier les onglets d'un changement.

#core#navigateur#communication

Bun

JavaScript 🟡 Mid

Runtime JavaScript/TypeScript tout-en-un (exécution, gestionnaire de paquets, bundler, runner de tests) bâti sur JavaScriptCore. Bun 1.4 (20 août 2026) est la première version issue de la réécriture complète de Zig vers Rust ; elle annonce +1 517 tests de la suite Node.js qui passent, 100 % sur node:events et node:sqlite, un démarrage deux fois plus rapide et des API intégrées comme Bun.Image, Bun.markdown, Bun.cron ou Bun.WebView.

Un couteau suisse : moins spécialisé que chaque outil séparé, mais un seul objet dans la poche.

// serveur.ts — lancé par : bun serveur.ts (TypeScript natif)
Bun.serve({
  port: 3000,
  routes: {
    '/static/*': { dir: './public' }, // fichiers statiques intégrés
  },
  fetch(req) {
    return new Response(Bun.markdown.html('# Bonjour **Bun**'));
  },
});
// bun install, bun test --parallel, bun build --compile

Cas d'usage : Scripts, API légères, monorepos où le temps d'installation compte ; CI (bun install annoncé 15 fois plus rapide que npm sur un projet Next.js).

Anti-pattern : Migrer un serveur de production sur Bun sans vérifier module par module la compatibilité Node (node:http, node:fs à 97 %, pas 100 %).
#tooling#runtime#bun

Call Stack

JavaScript 🟢 Junior? entretien

Pile LIFO (Last In, First Out) qui trace les contextes d'exécution des fonctions en cours. Chaque appel de fonction empile un frame, chaque return le depile.

Une pile d'assiettes : tu poses la dernière en haut et tu reprends toujours celle du dessus.

function a() { b(); }
function b() { c(); }
function c() { console.trace(); }
a();
// c -> b -> a -> global

Cas d'usage : Lire les stack traces d'erreurs et comprendre les dépassements de pile (stack overflow).

Anti-pattern : Récursion infinie sans condition d'arrêt qui provoque un Maximum call stack size exceeded.
#core#interview#debug

Callback Queue

JavaScript 🟡 Mid? entretien

File d'attente (macrotask queue) ou sont places les callbacks de setTimeout, setInterval, I/O et evenements DOM. Traites après que la call stack et la microtask queue sont vides.

La file d'attente normale a la poste : tu passes après les clients prioritaires (microtasks).

setTimeout(() => console.log('macro'), 0);
Promise.resolve().then(() => console.log('micro'));
// micro, macro

Cas d'usage : Planifier des taches non-urgentes qui ne doivent pas bloquer le rendu ou les promesses en cours.

#core#interview#async

Circular Dependencies

JavaScript 🔴 Senior

Situation ou le module A importe B et B importe A. En CommonJS, on obtient un export partiel. En ESM, ca fonctionne grâce aux live bindings mais peut causer des bugs subtils.

Deux personnes qui se tiennent la porte mutuellement : ca fonctionne si l'une passe en premier, mais ca peut devenir un blocage.

// a.js
import { b } from './b.js';
export const a = 'A' + b;
// b.js
import { a } from './a.js';
export const b = 'B'; // a est undefined ici en CJS!

Cas d'usage : Détecter et casser les cycles avec des outils comme madge ou eslint-plugin-import.

Anti-pattern : Ignorer les circular dependencies : elles causent des undefined mystérieux et du code fragile.
#core#modules#debug

Closure

JavaScript 🟡 Mid? entretien

Fonction qui capture et retient les variables de son scope parent même après que celui-ci a termine son exécution. C'est le mécanisme fondamental derrière les callbacks, modules et data privacy en JS.

Un sac a dos que tu emportes en quittant la maison : même loin de chez toi, tu as toujours accès a ce que tu y as mis.

function counter() {
  let count = 0;
  return {
    increment: () => ++count,
    get: () => count
  };
}
const c = counter();
c.increment(); // 1

Cas d'usage : Encapsuler un état prive dans un module ou créer des fonctions factory avec configuration injectée.

Anti-pattern : Créer des closures dans une boucle var sans IIFE : toutes les callbacks partagent la même variable.
#core#interview#fondamental

CommonJS vs ESM

JavaScript 🟡 Mid? entretien

CommonJS (require/module.exports) est synchrone et historique dans Node.js ; ESM (import/export) est le standard du langage, statique et propice au tree shaking. Les deux mondes communiquent désormais : require() d'un module ESM synchrone est activé par défaut depuis Node 22.12.0 et 20.19.0, et déclaré stable en Node 25.4.0. Un module avec top-level await reste inaccessible à require() (ERR_REQUIRE_ASYNC_MODULE).

CommonJS = commander par téléphone (dynamique, a la demande). ESM = liste de courses pre-écrite (statique, analysable a l'avance).

// lib.mjs (ESM)
export const lire = (p) => p;

// app.cjs (CommonJS) — Node ≥ 22.12 / 20.19
const { lire } = require('./lib.mjs'); // OK si pas de top-level await
if (process.features.require_module) {
  console.log('require(esm) disponible');
}

Cas d'usage : ESM pour tout nouveau code ; publier en ESM seul devient viable puisque les consommateurs CommonJS peuvent faire require(esm). TypeScript 5.8 modélise ce comportement avec --module nodenext.

Anti-pattern : Publier un paquet en double format CJS+ESM « par sécurité » alors que la cible Node supporte require(esm) : deux copies, deux jeux de .d.ts, singletons dupliqués.
#core#modules#interview#node22

Compose / Pipe

JavaScript 🟡 Mid

Compose enchaîné des fonctions de droite a gauche, pipe de gauche a droite. Chaque fonction reçoit le résultat de la précédenté. Fondamental en programmation fonctionnelle.

Une chaîne de montage : chaque poste (fonction) transforme le produit et le passe au suivant.

const pipe = (...fns) => (x) =>
  fns.reduce((acc, fn) => fn(acc), x);
const transform = pipe(
  str => str.trim(),
  str => str.toLowerCase(),
  str => str.replace(/\s+/g, '-')
);
transform('  Hello World  '); // 'hello-world'

Cas d'usage : Transformation de données en pipeline, middleware, traitement de texte, ETL.

#core#fonctionnel#pattern

Currying

JavaScript 🟡 Mid

Transformer une fonction a N arguments en N fonctions a 1 argument chainables. Chaque appel retourne une nouvelle fonction jusqu'a ce que tous les arguments soient fournis.

Un formulaire en plusieurs étapes : chaque page collecte une info, et le formulaire n'est soumis qu'a la dernière étape.

const curry = (fn) => {
  const arity = fn.length;
  return function go(...args) {
    return args.length >= arity
      ? fn(...args)
      : (...more) => go(...args, ...more);
  };
};
const add = curry((a, b, c) => a + b + c);
add(1)(2)(3); // 6

Cas d'usage : Configuration progressive de fonctions, création de variantes spécialisées, composition fonctionnelle.

#core#fonctionnel#pattern

Debounce

JavaScript 🟡 Mid? entretien

Retarde l'exécution d'une fonction jusqu'a ce qu'un délai se soit écoulé sans nouvel appel. Chaque appel réinitialisé le timer. N'exécuté que le dernier appel.

L'ascenseur qui attend que plus personne n'entre pendant 3 secondes avant de fermer les portes.

function debounce(fn, ms) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), ms);
  };
}
const search = debounce(query => fetch(query), 300);

Cas d'usage : Recherche en temps réel (attendre que l'utilisateur arrête de taper), resize handler, auto-save.

Anti-pattern : Debounce avec un délai trop long qui rend l'interface non-réactivé.
#core#performance#pattern#interview

Deno 2

JavaScript 🟡 Mid

Runtime JavaScript/TypeScript sécurisé par défaut, avec TypeScript natif, formateur, linter et runner de tests intégrés. Deno 2.0 (9 octobre 2024) a apporté la compatibilité Node/npm (package.json, node_modules, spécificateurs npm:), le registre JSR et les workspaces. Deno 2.8 (22 mai 2026) implémente import defer ; Deno 2.9 (25 juin 2026) lit directement les lockfiles npm/pnpm/yarn/Bun, ajoute deno desktop et annonce un démarrage à froid deux fois plus rapide (17,3 ms).

Un navigateur pour le serveur : rien n'est autorisé tant que l'utilisateur n'a pas dit oui.

// main.ts — lancé par : deno run --allow-net=api.exemple.fr main.ts
import chalk from 'npm:chalk@5';           // paquet npm direct
import { assert } from 'jsr:@std/assert';   // registre JSR

const res = await fetch('https://api.exemple.fr/ping');
assert(res.ok);
console.log(chalk.green('ok'));
// Lire un fichier sans --allow-read → PermissionDenied

Cas d'usage : Scripts d'administration, edge functions, projets qui veulent des permissions explicites et zéro configuration TypeScript.

Anti-pattern : Lancer tout avec --allow-all (-A) par habitude : on perd l'intérêt principal du runtime.
#tooling#runtime#deno#securite

Destructuring

JavaScript 🟢 Junior

Syntaxe ES6 pour extraire des valeurs d'objets ou tableaux dans des variables distinctes. Supporte les valeurs par défaut, le renommage et l'imbrication.

Ouvrir un colis et ranger chaque article directement dans le bon tiroir au lieu de tout laisser dans le carton.

const { name, age = 25 } = user;
const [first, ...rest] = [1, 2, 3];
// Nested
const { address: { city } } = user;
// Rename
const { name: userName } = user;

Cas d'usage : Extraire proprement les props d'un composant React, les champs d'une réponse API, les arguments de fonction.

Anti-pattern : Déstructurer trop profondément en une ligne, rendant le code illisible.
#core#ES6#syntaxe

Dynamic Import

JavaScript 🟡 Mid

import() est une expression qui renvoie une promesse du module : chargement conditionnel et découpage du code à l'exécution. Le second argument accepte des attributs d'import (ES2025) : import('./data.json', { with: { type: 'json' } }). Pour différer seulement l'évaluation (et non le chargement), la proposition « import defer » (Stage 3) est supportée par TypeScript 5.9 et Deno 2.8.

Commander un plat a la carte au lieu du menu complet : tu ne charges que ce dont tu as besoin, quand tu en as besoin.

const chargerGraphe = async () => {
  const { Chart } = await import('./chart.js');
  return new Chart(data);
};
// Attribut d'import (ES2025) : JSON en module
const { default: conf } = await import('./conf.json', {
  with: { type: 'json' }
});
if (user.isAdmin) {
  const { AdminPanel } = await import('./admin.js');
}

Cas d'usage : Code splitting dans les SPA, chargement lazy de routes/composants lourds, chargement conditionnel.

#core#performance#modules#ES2025

Error Types

JavaScript 🟢 Junior

JS a des types d'erreurs built-in : TypeError (mauvais type), ReferenceError (variable inconnue), SyntaxError, RangeError, URIError. On peut créer des erreurs custom via extends Error.

Différents codes d'alerte dans un hôpital : chaque type indique immédiatement la nature du problème.

class AppError extends Error {
  constructor(message, code) {
    super(message);
    this.name = 'AppError';
    this.code = code;
  }
}
throw new AppError('Not found', 404);

Cas d'usage : Créer des erreurs métier typées pour un meilleur handling et des messages clairs.

Anti-pattern : throw 'string' au lieu de throw new Error('string') : pas de stack trace.
#core#fondamental#best-practice

Error.isError()

JavaScript 🟡 Mid

Méthode statique (Stage 4, listée par TC39 pour ES2026) qui indique si une valeur est un vrai objet Error, y compris DOMException, via une marque interne posée par le constructeur, comme Array.isArray. Elle fonctionne entre realms (iframe, vm, worker) là où instanceof Error échoue, et rejette un objet qui n'a fait qu'emprunter Error.prototype. Livrée dans V8 13.6 (Node.js 24) ; support navigateur encore incomplet selon MDN.

Vérifier le tampon officiel d'un document plutôt que le papier à en-tête, qui s'imite.

try {
  throw 'chaîne brute';
} catch (e) {
  if (!Error.isError(e)) e = new Error(String(e)); // normaliser
  console.error(e.message);
}
Error.isError(new TypeError()); // true
Error.isError({ __proto__: Error.prototype }); // false
// Erreur venue d'une iframe : instanceof Error → false, isError → true

Cas d'usage : Bibliothèques de journalisation, frontières iframe/worker/vm, normalisation des valeurs rejetées.

Anti-pattern : Se fier à instanceof Error dans du code multi-realm : faux négatifs garantis.
#core#ES2026#node24

ESM-only (fin du double format)

JavaScript 🟡 Mid

Pratique de publier un paquet npm uniquement en modules ES, sans build CommonJS parallèle. Elle est devenue défendable depuis que require(esm) est activé par défaut dans Node 22.12.0 et 20.19.0 (stable en 25.4.0) : un consommateur CommonJS peut charger le paquet. L'article « Move on to ESM-only » (5 février 2025) chiffre l'adoption d'ESM sur npm à 25,8 % fin 2024 et liste les coûts du double format : deux jeux de fichiers et de .d.ts, singletons dupliqués, taille doublée.

Arrêter d'imprimer un journal en deux formats quand tous les kiosques acceptent le nouveau.

{
  "name": "ma-lib",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "engines": { "node": ">=20.19" }
}

Cas d'usage : Nouvelles bibliothèques, outils en ligne de commande, paquets destinés au navigateur (tree shaking) ou aux versions de Node qui supportent require(esm).

Anti-pattern : Garder un top-level await dans le point d'entrée d'une lib ESM-only : les consommateurs CommonJS ne pourront plus la require().
#best-practice#modules#node22

Event Bubbling / Capturing

JavaScript 🟡 Mid

Deux phases de propagation des evenements DOM. Capturing descend du document vers la cible, bubbling remonte de la cible vers le document. Par défaut, les listeners écoûtent en phase bubbling.

Capturing = le facteur descend l'escalier pour trouver la bonne porte. Bubbling = la nouvelle remonte de voisin en voisin jusqu'au concierge.

// Bubbling (defaut)
el.addEventListener('click', handler);
// Capturing
el.addEventListener('click', handler, true);
// Ou avec options
el.addEventListener('click', handler, {
  capture: true
});

Cas d'usage : Intercepter des evenements avant qu'ils n'atteignent leur cible (capture), ou déléguer après (bubbling).

#core#DOM

Event Delegation

JavaScript 🟢 Junior? entretien

Attacher un seul event listener sur un parent au lieu d'un sur chaque enfant. Exploite le bubbling pour capturer les evenements des descendants via event.target.

Un standardiste unique qui reçoit tous les appels de l'immeuble et les redirigé vers le bon bureau.

document.getElementById('list')
  .addEventListener('click', (e) => {
    if (e.target.matches('li.item')) {
      handleClick(e.target.dataset.id);
    }
  });

Cas d'usage : Listes dynamiques, tableaux avec beaucoup de lignes, éléments ajoutes après le chargement.

Anti-pattern : Attacher un listener a chaque élément d'une liste de 1000 items au lieu de déléguer au parent.
#core#DOM#performance#interview

Event Emitter Pattern

JavaScript 🟡 Mid

Pattern publish/subscribe ou un émetteur envoie des evenements nommes et des listeners s'y abonnent. Base de EventTarget (DOM) et EventEmitter (Node.js).

Une radio : l'émetteur diffuse sur une fréquence (evenement) et tous les récepteurs branches sur cette fréquence captent le message.

class Emitter {
  #events = {};
  on(evt, fn) {
    (this.#events[evt] ??= []).push(fn);
  }
  emit(evt, ...args) {
    this.#events[evt]?.forEach(fn => fn(...args));
  }
}
const bus = new Emitter();
bus.on('data', console.log);

Cas d'usage : Communication découplé entre composants, bus d'evenements, architecture event-driven.

Anti-pattern : Ne jamais off() les listeners, causant des memory leaks et des callbacks zombies.
#core#pattern#architecture

Event Loop

JavaScript 🟡 Mid? entretien

Mécanisme central qui gère l'exécution asynchrone en JS. Il surveille la call stack et, quand elle est vide, depile les callbacks des queues (microtask d'abord, puis macrotask).

Un serveur de restaurant qui sert les plats quand le client a fini de manger : il attend que la table soit libre avant d'apporter le suivant.

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// 1, 4, 3, 2

Cas d'usage : Comprendre l'ordre d'exécution du code asynchrone et debugger les problèmes de timing.

Anti-pattern : Croire que setTimeout(fn, 0) s'exécute immédiatement après le code synchrone (les microtasks passent avant).
#core#interview#performance#fondamental

Execution Context

JavaScript 🔴 Senior? entretien

Environnement abstrait dans lequel le code JS est évalué. Contient le Variable Environment, le Lexical Environment et la valeur de this. Créé pour chaque appel de fonction et le scope global.

La fiche d'identité d'un appel de fonction : qui elle est (this), ce qu'elle connaît (variables), et d'ou elle vient (scope).

// Global EC cree au demarrage
const x = 1;
function foo() {
  // Nouveau EC pour foo()
  const y = 2;
  console.log(x + y); // accede au parent EC
}
foo();

Cas d'usage : Comprendre en profondeur le comportement de this, le hoisting et la scope chain.

#core#interview#avance

Explicit Resource Management (using)

JavaScript 🔴 Senior

Le mot-clé using déclare une variable dont la méthode [Symbol.dispose]() est appelée automatiquement à la sortie du bloc ; await using fait de même avec [Symbol.asyncDispose](). La proposition « Explicit Resource Management » est terminée (Stage 4) et figure dans la liste TC39 des propositions attendues pour l'édition ES2027. Elle est déjà livrée dans V8 13.6, donc dans Node.js 24 (6 mai 2025), et TypeScript la compile depuis la 5.2. Équivalent du try-with-resources de Java ou du using de C#.

Un robinet auto-coupant : il se ferme tout seul quand tu quittes la pièce, pas besoin de penser a le fermer.

class Conn {
  [Symbol.dispose]() { console.log('connexion fermée'); }
}
function requete() {
  using db = new Conn();      // libéré à la sortie du bloc
  using pile = new DisposableStack();
  pile.defer(() => console.log('nettoyage différé'));
  return 'ok';
} // ordre inverse : pile puis db
// async : await using s = await ouvrirSocket();

Cas d'usage : Connexions base de données, descripteurs de fichiers, verrous, transactions : tout ce qui exige un nettoyage garanti même en cas d'exception. DisposableStack regroupe plusieurs ressources à libérer dans l'ordre inverse.

Anti-pattern : Utiliser using sur un objet sans [Symbol.dispose] : TypeError à l'exécution. Ignorer SuppressedError, qui agrège l'erreur du bloc et celle survenue pendant la libération.
#core#avance#ES2027#node24

Fetch API

JavaScript 🟢 Junior

API moderne de requêtes HTTP basée sur les Promises, remplaçant XMLHttpRequest. Retourne une Response avec des méthodes pour parser le body (json, text, blob, etc.).

Un service de livraison moderne : tu passes commande (fetch), tu reçois un bon de livraison (Response), puis tu ouvres le colis (.json()).

const res = await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Alice' })
});
if (!res.ok) throw new Error(res.status);
const data = await res.json();

Cas d'usage : Toute communication HTTP : appels API REST, upload de fichiers, téléchargement de ressources.

Anti-pattern : Oublier de vérifier res.ok : fetch ne rejette PAS sur les erreurs HTTP (404, 500, etc.).
#core#async#navigateur#fondamental

FinalizationRegistry

JavaScript 🔴 Senior

API qui permet d'enregistrer un callback de nettoyage appelé quand un objet observe est garbage-collecte. Companion de WeakRef pour le cleanup de ressources.

Un notaire qui exécute le testament (cleanup) quand la personne (objet) n'est plus la.

const registry = new FinalizationRegistry((heldValue) => {
  console.log(`Cleaned up: ${heldValue}`);
});
let obj = { heavy: new ArrayBuffer(1e6) };
registry.register(obj, 'heavy-buffer');
obj = null; // callback sera appele au GC

Cas d'usage : Libération de ressources externes (handles fichier, connexions) quand l'objet JS associe est GC.

Anti-pattern : Se baser sur FinalizationRegistry pour une logique critique : le callback peut ne jamais être appelé.
#core#avance#ES2021

for...of vs for...in

JavaScript 🟢 Junior? entretien

for...of itere sur les valeurs des iterables (Array, Map, Set, String). for...in itere sur les clés enumerables d'un objet, y compris la prototype chain.

for...of = lire chaque page d'un livre. for...in = lire la table des matières (et potentiellement celles des annexes héritées).

const arr = ['a', 'b', 'c'];
for (const val of arr) console.log(val); // a, b, c
for (const idx in arr) console.log(idx); // 0, 1, 2

const obj = { x: 1, y: 2 };
for (const key in obj) console.log(key); // x, y

Cas d'usage : for...of pour les tableaux et iterables, for...in pour les propriétés d'objets (avec hasOwnProperty).

Anti-pattern : Utiliser for...in sur un tableau : parcourt aussi les propriétés du prototype et les index sont des strings.
#core#fondamental#interview

Garbage Collection

JavaScript 🟡 Mid

Processus automatique de libération de la mémoire non référencée. V8 utilise un GC generationnel : minor GC (young génération) fréquent et major GC (old génération) moins souvent.

Un service de nettoyage qui ramasse les objets abandonnes dans un parc : si personne ne les réclame, ils sont jetés.

let obj = { data: new Array(1000000) };
// obj est referencee, pas GC
obj = null;
// Plus de reference -> eligible au GC
// WeakRef pour reference faible
const weak = new WeakRef(someObj);

Cas d'usage : Comprendre les fuites mémoire, optimiser l'allocation, choisir entre Map/WeakMap.

#core#performance#engine

Generator

JavaScript 🟡 Mid

Fonction spéciale (function*) qui peut se suspendre via yield et reprendre. Retourne un itérateur. Permet la génération paresseuse de séquences potentiellement infinies.

Un livre dont tu tournes les pages une par une (yield) : l'histoire ne se déroule que quand tu le demandes.

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}
const fib = fibonacci();
fib.next().value; // 0, 1, 1, 2...

Cas d'usage : Séquences paresseuses, pagination, flux de données, implémentation de iterables custom.

#core#ES6#avance

Hoisting

JavaScript 🟢 Junior? entretien

Mécanisme par lequel les déclarations de variables (var) et fonctions sont remontées en haut de leur scope durant la phase de compilation. Les let/const sont hoistees mais restent dans la Temporal Dead Zone.

Comme un prof qui note tous les noms au tableau avant le début du cours, mais ne remplit les notes qu'au fur et a mesure.

console.log(a); // undefined (var hoiste)
var a = 5;

sayHi(); // OK, declaration hoistee
function sayHi() { console.log('Hi'); }

console.log(b); // ReferenceError (TDZ)
let b = 10;

Cas d'usage : Comprendre pourquoi une variable vaut undefined au lieu de lancer une erreur, debugger l'ordre d'exécution.

Anti-pattern : Utiliser var et compter sur le hoisting au lieu de déclarer les variables en haut du scope.
#core#interview#fondamental

IIFE

JavaScript 🟢 Junior

Immediately Invoked Function Expression : fonction anonyme exécutée immédiatement a sa déclaration. Créé un scope isole pour éviter la pollution globale. Moins utile depuis les modules ESM.

Un feu d'artifice a usage unique : tu l'allumes et il s'exécute immédiatement, sans laisser de trace.

const result = (() => {
  const secret = 42;
  return secret * 2;
})();
// secret n'existe pas ici
console.log(result); // 84

Cas d'usage : Isolation de scope dans du code legacy, initialisation immédiate, éviter les collisions globales.

#core#pattern#legacy

Immutability

JavaScript 🟡 Mid

Principe de ne jamais modifier les données existantes mais de créer de nouvelles copies avec les changements. Object.freeze() pour une immutabilite superficielle en JS natif.

Un livre publie : pour corriger une erreur, tu publies une nouvelle édition au lieu de rayer l'ancienne.

// Immutable update
const user = { name: 'Alice', age: 30 };
const updated = { ...user, age: 31 };
// Array
const arr = [1, 2, 3];
const added = [...arr, 4];
// Freeze
const frozen = Object.freeze({ x: 1 });

Cas d'usage : State management (Redux, React state), historique undo/redo, détection de changements performante.

Anti-pattern : Croire que Object.freeze est profond : les objets imbriques restent mutables.
#core#fonctionnel#principe

Import Attributes (with)

JavaScript 🟡 Mid

Syntaxe ES2025 qui accole des métadonnées à un import : import data from './x.json' with { type: 'json' }. L'attribut type: 'json' est le seul défini par ECMAScript (« JSON modules », ES2025) ; les navigateurs ajoutent type: 'css'. L'ancienne forme assert est abandonnée. Node.js exige l'attribut pour importer un JSON et l'a déclaré stable en 22.12.0 et 20.18.3 ; TypeScript 6.0 déprécie assert.

L'étiquette « fragile » sur un colis : elle dit au transporteur comment traiter le contenu, pas ce qu'il est.

// Statique
import conf from './config.json' with { type: 'json' };
console.log(conf.port);

// Dynamique
const { default: i18n } = await import('./fr.json', {
  with: { type: 'json' }
});
// Navigateur : feuille de style comme module
// import feuille from './app.css' with { type: 'css' };

Cas d'usage : Configuration, traductions, fixtures : importer du JSON sans fs.readFile ni bundler.

Anti-pattern : Importer un JSON sans l'attribut : Node lève une erreur, et le navigateur refuse par sécurité (type MIME non vérifié).
#core#ES2025#modules#node22

import defer

JavaScript 🔴 Senior

Proposition TC39 au Stage 3 (« Deferring Module Évaluation ») : import defer * as ns from './lourd.js' charge et lie le module tout de suite mais n'exécute son code qu'au premier accès à une propriété de ns. Un module avec top-level await est évalué immédiatement. TypeScript 5.9 (1er août 2025) accepte la syntaxe et Deno 2.8 (22 mai 2026) l'exécute ; le support navigateur est encore limité.

Une pièce dont on a la clé sur soi mais dont on n'allume la lumière qu'en entrant.

import defer * as pdf from './generateur-pdf.js'; // lié, pas évalué
console.log('démarrage rapide');

export function exporter(doc) {
  // Première lecture d'une propriété : le module s'exécute ici
  return pdf.render(doc);
}
// Attention : les effets de bord du module sont déplacés aussi

Cas d'usage : Réduire le temps de démarrage d'une CLI ou d'un serveur qui charge de gros modules rarement utilisés, sans rendre le code appelant asynchrone.

Anti-pattern : Différer un polyfill ou un module qui enregistre des effets globaux : ils ne s'appliqueraient plus au bon moment.
#avance#stage3#modules#performance

Import Maps

JavaScript 🔴 Senior

API navigateur via <script type='importmap'> qui mappe des specifiers de modules a des URLs. Permet d'utiliser des bare imports sans bundler.

Un annuaire qui traduit les noms (lodash) en adresses réelles (https://cdn.../lodash.js).

<script type="importmap">
{ "imports": { "lodash": "/libs/lodash.js" } }
</script>
<script type="module">
import _ from 'lodash';
</script>

Cas d'usage : Prototypage rapide sans bundler, migration progressive vers ESM natif dans le navigateur.

#core#modules#navigateur

Inline Caching

JavaScript 🔴 Senior

Optimisation V8 qui cache l'emplacement mémoire d'une propriété après le premier accès. Monomorphique (1 type) = rapide, polymorphique (2-4) = OK, megamorphique (5+) = lent.

Se souvenir exactement ou tu as range tes clés (toujours la même poche) au lieu de fouiller partout a chaque fois.

// Monomorphique (rapide)
function getX(obj) { return obj.x; }
getX({ x: 1 }); getX({ x: 2 }); // meme forme

// Megamorphique (lent)
getX({ x: 1 });
getX({ x: 1, y: 2 });
getX({ x: 1, z: 3 });
getX({ a: 0, x: 1 }); // formes differentes

Cas d'usage : Garder des formes d'objets cohérentes dans les hot paths pour maximiser les performances V8.

#core#engine#performance

IntersectionObserver

JavaScript 🟡 Mid

API qui observe de manière asynchrone la visibilité d'un élément par rapport a un ancêtre ou au viewport. Remplace les calculs manuels de getBoundingClientRect dans un scroll listener.

Un vigile qui te prévient automatiquement quand quelqu'un entre dans la zone de surveillance, sans que tu doives regarder constamment.

const observer = new IntersectionObserver(
  (entries) => entries.forEach(e => {
    if (e.isIntersecting) loadImage(e.target);
  }),
  { threshold: 0.1 }
);
document.querySelectorAll('img[data-src]')
  .forEach(img => observer.observe(img));

Cas d'usage : Lazy loading d'images, infinité scroll, animations au scroll, tracking d'impressions.

Anti-pattern : Utiliser un scroll event listener avec getBoundingClientRect pour détecter la visibilité.
#core#DOM#performance

Iterator Helpers

JavaScript 🟡 Mid

Méthodes paresseuses sur les itérateurs natifs, standardisées dans ES2025 : map, filter, take, drop, flatMap, reduce, forEach, some, every, find et toArray, plus Iterator.from pour envelopper un itérable quelconque. Chaque étape consomme les valeurs à la demande, sans tableau intermédiaire, ce qui permet de traiter des séquences infinies. ES2026 ajoute Iterator.concat.

Une chaîne de montage où chaque pièce passe de poste en poste, au lieu d'empiler toutes les pièces entre chaque poste.

function* naturels() { let n = 1; while (true) yield n++; }

const carresPairs = naturels()
  .filter(n => n % 2 === 0)
  .map(n => n * n)
  .take(3)
  .toArray(); // [4, 16, 36] — l'infini n'est jamais parcouru

// Map.values() sans copie en tableau
const total = stocks.values().reduce((a, b) => a + b, 0);

Cas d'usage : Traiter des flux ou de grandes collections (Map, Set, générateurs) sans copies ; lire un générateur infini par morceaux.

Anti-pattern : Appeler [...itérateur].map(...) par réflexe : on perd la paresse et on alloue un tableau complet.
#core#ES2025#performance

Iterator Protocol

JavaScript 🟡 Mid

Convention par laquelle un objet produit une séquence : il est itérable s'il expose [Symbol.iterator]() retournant un itérateur dont next() renvoie {value, done}. Depuis ES2025, les itérateurs natifs héritent de la classe globale Iterator et disposent des « iterator helpers » (map, filter, take, drop, flatMap, reduce, toArray…), et Iterator.concat arrive avec ES2026.

Un distributeur de tickets : chaque appel a next() te donne le ticket suivant, et done te dit quand il n'y en a plus.

const range = {
  from: 1, to: 3,
  [Symbol.iterator]() {
    let n = this.from;
    return { next: () => n <= this.to
      ? { value: n++, done: false }
      : { done: true } };
  }
};
for (const n of range) console.log(n);

Cas d'usage : Rendre des objets maison utilisables dans for...of, spread et destructuring ; enchaîner des transformations paresseuses sans créer de tableaux intermédiaires.

#core#ES6#ES2025#pattern

JIT Compilation

JavaScript 🔴 Senior

Compilation Just-In-Time : V8 interprété d'abord le bytecode (Ignition), puis compile en code machine optimise (TurboFan) les fonctions chaudes. Peut desoptimiser si les hypothèses sont invalides.

Un cuisinier qui improvise la première fois (interprétation), puis écrit la recette (compilation) quand il a assez d'expérience avec le plat.

// V8 pipeline:
// 1. Parser -> AST
// 2. Ignition -> Bytecode (interprete)
// 3. Profiling (quelles fonctions sont chaudes?)
// 4. TurboFan -> Code machine optimise
// 5. Deopt si les types changent

Cas d'usage : Comprendre pourquoi le code JS est rapide malgré le typage dynamique, et comment éviter les deoptimisations.

#core#engine#performance

Lexical Scope

JavaScript 🟡 Mid? entretien

Le scope d'une variable est déterminé par l'endroit ou elle est écrite dans le code source, pas par l'endroit ou la fonction est appelée. C'est la base des closures en JS.

Ton adresse postale dépend d'ou tu habites, pas d'ou tu te trouves quand tu reçois le courrier.

const x = 'global';
function foo() {
  console.log(x); // 'global' (scope lexical)
}
function bar() {
  const x = 'bar';
  foo(); // affiche 'global', pas 'bar'
}

Cas d'usage : Prédire le comportement des closures et comprendre pourquoi JS n'utilise pas le dynamic scoping.

#core#interview

Logical Assignment

JavaScript 🟢 Junior

Opérateurs &&=, ||= et ??= qui combinent affectation et logique. a ??= b assigne b a a seulement si a est null/undefined. Court-circuitage préserve.

Remplir un formulaire pre-rempli : tu n'écris que dans les cases vides (??=), pas celles déjà remplies.

let opts = {};
opts.timeout ??= 5000;  // assigne si null/undefined
opts.debug ||= false;   // assigne si falsy
opts.verbose &&= true;  // assigne si truthy

Cas d'usage : Initialiser des options/configurations avec des valeurs par défaut de manière concise.

#core#ES2021#syntaxe

Map

JavaScript 🟢 Junior

Collection clé-valeur ordonnée ou les clés peuvent être de n'importe quel type (objets, fonctions, primitives). Plus performante qu'un objet pour les ajouts/suppressions fréquents.

Un casier de vestiaire ou chaque casier a une clé unique de n'importe quelle forme, pas juste une étiquette texte.

const cache = new Map();
const key = { id: 1 };
cache.set(key, 'data');
cache.get(key);  // 'data'
cache.has(key);  // true
cache.size;      // 1

Cas d'usage : Cache en mémoire, compteurs de fréquences, lookup tables avec des clés non-string.

Anti-pattern : Utiliser un objet plain comme map avec des clés utilisateur non sanitisees (risque de prototype pollution).
#core#ES6#performance

Map.getOrInsert() (Upsert)

JavaScript 🟢 Junior

Proposition « Upsert » (Stage 4, listée par TC39 pour ES2026) : Map et WeakMap gagnent getOrInsert(clé, valeur) qui renvoie la valeur existante ou insère puis renvoie la valeur par défaut, et getOrInsertComputed(clé, fn) qui ne calcule la valeur que si la clé manque. Livrée dans V8 14.6, donc dans Node.js 26 (5 mai 2026) ; disponible dans les navigateurs majeurs depuis février 2026.

Le porte-manteau du restaurant : si votre crochet existe on vous le rend, sinon on en installe un et on vous le donne.

const parVille = new Map();
for (const client of clients) {
  // Avant : if (!m.has(k)) m.set(k, []); m.get(k).push(...)
  parVille.getOrInsert(client.ville, []).push(client);
}
// Calcul coûteux seulement si absent
const cache = new Map();
const r = cache.getOrInsertComputed(url, () => calculerLourd(url));

Cas d'usage : Regroupements (multimap), caches mémoïsés, compteurs : le motif has/get/set en une ligne.

Anti-pattern : Utiliser getOrInsert avec une valeur par défaut coûteuse à construire : elle est créée même si la clé existe ; prendre getOrInsertComputed.
#core#ES2026#node26

Mark-and-Sweep

JavaScript 🔴 Senior

Algorithme de GC utilise par V8 : phase Mark parcourt le graphe d'objets depuis les racines (global, stack) et marque les atteignables. Phase Sweep libéré les non-marques.

Un inventaire d'entrepôt : tu coches (mark) tout ce qui est sur la liste de commandes, puis tu jettes (sweep) le reste.

// Racines GC: global, stack, registres
// Atteignable = survit
window.app = { data: [1,2,3] }; // atteignable via window
// Non atteignable = GC
function leak() {
  const huge = new Array(1e6);
  // huge est GC apres retour de leak()
}

Cas d'usage : Comprendre pourquoi certains objets ne sont pas collectes et diagnostiquer les fuites mémoire.

#core#engine#performance

Memoization

JavaScript 🟡 Mid

Technique de cache qui stocke le résultat d'un appel de fonction base sur ses arguments. Si les mêmes arguments sont repasses, le résultat est retourne du cache sans recalcul.

Un carnet de notes : avant de recalculer, tu vérifies si tu as déjà note la réponse.

function memoize(fn) {
  const cache = new Map();
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

Cas d'usage : Fonctions de calcul coûteux appelées fréquemment avec les mêmes paramètrès (fibonacci, selectors Redux).

Anti-pattern : Memoiser des fonctions avec des effets de bord ou des arguments non serialisables.
#core#performance#fonctionnel

Memory Leak Patterns

JavaScript 🔴 Senior

Patterns courants de fuites mémoire : event listeners non retires, closures retenant de gros objets, références DOM détachées, timers oublies, caches non bornes.

Des robinets qui fuient dans la maison : individuellement c'est rien, mais au bout d'un mois la facture d'eau explose.

// Fuite: listener jamais retire
window.addEventListener('resize', handler);
// Fuite: closure retient tout le scope
function init() {
  const bigData = new Array(1e6);
  return () => console.log(bigData.length);
}
// Fix: retirer les listeners, nullifier les refs

Cas d'usage : Debugger les apps qui ralentissent avec le temps, onglets qui consomment de plus en plus de RAM.

Anti-pattern : Ignorer le cleanup dans useEffect (React) ou ngOnDestroy (Angular).
#core#performance#debug

Microtask Queue

JavaScript 🟡 Mid? entretien

File prioritaire qui contient les callbacks de Promises (.then/.catch/.finally), MutationObserver et queueMicrotask. Vidée entièrement avant chaque macrotask.

Les clients VIP qui passent devant tout le monde a chaque tour de service.

queueMicrotask(() => console.log('micro 1'));
setTimeout(() => console.log('macro'), 0);
queueMicrotask(() => console.log('micro 2'));
// micro 1, micro 2, macro

Cas d'usage : Exécuter du code juste après l'opération courante mais avant le prochain rendu ou timer.

Anti-pattern : Créer des microtasks en boucle infinie qui bloquent complètement la macrotask queue et le rendu.
#core#interview#async

MutationObserver

JavaScript 🟡 Mid

API qui observe les changements du DOM (attributs, enfants, texte) de manière asynchrone et performante. Remplace les deprecated Mutation Events.

Une caméra de surveillance qui enregistre chaque modification dans une pièce et te fait un rapport groupe.

const observer = new MutationObserver((mutations) => {
  mutations.forEach(m => console.log(m.type));
});
observer.observe(document.body, {
  childList: true,
  subtree: true,
  attributes: true
});

Cas d'usage : Détecter des modifications DOM par des scripts tiers, synchroniser un état externe avec le DOM.

#core#DOM

new keyword

JavaScript 🟡 Mid? entretien

Opérateur qui crée une instance : 1) créé un objet vide, 2) lie son [[Prototype]] au .prototype du constructeur, 3) exécuté le constructeur avec this = nouvel objet, 4) retourne l'objet.

Un moule a gâteau : new prend le moule (constructeur), verse la pâte (propriétés), et te donne un gâteau (instance).

function User(name) {
  this.name = name;
}
User.prototype.hi = function() { return this.name; };
const u = new User('Alice');
u.hi(); // 'Alice'

Cas d'usage : Instancier des objets a partir de constructeurs ou de classes ES6.

Anti-pattern : Oublier new devant un constructeur : this pointe alors vers global/undefined et les propriétés fuient.
#core#interview#OOP

Node.js Permission Model

JavaScript 🔴 Senior

Modèle de permissions intégré à Node.js : lancé avec --permission, le processus se voit refuser (ERR_ACCESS_DENIED) l'accès au système de fichiers, aux processus enfants, aux workers, au réseau, aux addons natifs, à WASI et au FFI, sauf autorisation explicite (--allow-fs-read, --allow-fs-write, --allow-child-process, --allow-net…). Ajouté en 20.0.0 en expérimental, il est stable depuis 23.5.0 et 22.13.0 ; --permission-audit journalise les violations sans bloquer.

Un badge d'accès qui n'ouvre que les portes listées, plutôt qu'un passe-partout.

# Refuse tout sauf lecture de ./config et écriture de ./logs
node --permission \
  --allow-fs-read=./config \
  --allow-fs-write=./logs \
  app.js

# Phase de découverte : journaliser sans bloquer
node --permission-audit --allow-fs-read=/tmp app.js

# Dans le code : process.permission.has('fs.write', './logs') → true

Cas d'usage : Exécuter des scripts tiers, des dépendances peu fiables ou des workers d'IA avec un périmètre borné.

Anti-pattern : Lancer --permission avec --allow-fs-read=* --allow-fs-write=* : le modèle est actif mais n'interdit plus rien d'utile.
#securite#node22#node23#avance

Node.js Test Runner (node:test)

JavaScript 🟢 Junior

Framework de test intégré à Node.js : module node:test (stable depuis la 20.0.0) et commande node --test. Il fournit describe/it, sous-tests, mocks (fonctions, modules, timers), snapshots, mode --watch, couverture (--expérimental-test-coverage) et rapporteurs spec, tap, dot, junit, lcov. Depuis Node 24, il attend automatiquement les sous-tests sans await manuel.

La trousse de secours livrée avec la voiture : pas la plus complète, mais toujours là.

// math.test.mjs — lancé par : node --test
import { test, mock } from 'node:test';
import assert from 'node:assert/strict';

test('addition', () => {
  assert.equal(1 + 1, 2);
});
test('mock', () => {
  const fn = mock.fn(() => 42);
  fn();
  assert.equal(fn.mock.callCount(), 1);
});

Cas d'usage : Bibliothèques et outils sans dépendance de test ; CI légère ; projets qui veulent éviter Jest ou Vitest.

Anti-pattern : Ajouter Jest pour trois tests unitaires dans un paquet Node : le runner natif suffit et démarre plus vite.
#tooling#node20#node24#tests

node:sqlite

JavaScript 🟡 Mid

Module SQLite intégré à Node.js, ajouté en 22.5.0, sorti du drapeau --expérimental-sqlite en 23.4.0 et 22.13.0, et passé « release candidate » (stabilité 1.2) en 25.7.0. API synchrone : DatabaseSync, prépare(), run/get/all/iterate, plus un SQLTagStore qui met en cache des requêtes écrites en template literal. Bun 1.4 annonce 100 % de compatibilité avec ce module.

Un carnet de comptes rangé dans le tiroir du bureau : pas besoin d'aller à la banque pour une addition.

import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync('app.db'); // ou ':memory:'
db.exec('CREATE TABLE IF NOT EXISTS todo(id INTEGER PRIMARY KEY, txt TEXT) STRICT');
const ins = db.prepare('INSERT INTO todo (txt) VALUES (?)');
ins.run('acheter du pain');
const tous = db.prepare('SELECT * FROM todo').all();
console.log(tous); // [{ id: 1, txt: 'acheter du pain' }]
db.close();

Cas d'usage : CLI, prototypes, caches locaux, tests : une base relationnelle sans dépendance native ni serveur.

Anti-pattern : Utiliser l'API synchrone au cœur d'un serveur HTTP très sollicité : chaque requête bloque la boucle d'événements.
#tooling#node22#node25#donnees

Nullish Coalescing

JavaScript 🟢 Junior

Opérateur ?? qui retourne la valeur de droite uniquement si celle de gauche est null ou undefined (pas pour 0, '' ou false, contrairement a ||).

Un filet de sécurité qui ne se déclenche que si le trapéziste est vraiment absent (null/undefined), pas s'il est juste petit (0) ou silencieux ('').

const port = config.port ?? 3000;
// vs ||
0 || 3000;  // 3000 (bug!)
0 ?? 3000;  // 0 (correct)
'' ?? 'default'; // '' (correct)

Cas d'usage : Définir des valeurs par défaut en préservant les valeurs falsy légitimes comme 0, '' ou false.

#core#ES2020#syntaxe

Object Static Methods

JavaScript 🟡 Mid

Méthodes statiques clés : Object.keys/values/entries (énumération), Object.assign (copie shallow), Object.freeze/seal (immutabilite), Object.fromEntries (reconstruction), Object.create (prototype).

La boite a outils officielle pour manipuler les objets : chaque outil a un usage précis.

const obj = { a: 1, b: 2 };
Object.keys(obj);     // ['a', 'b']
Object.entries(obj);  // [['a',1], ['b',2]]
const copy = Object.assign({}, obj);
const fromMap = Object.fromEntries(new Map([['x',1]]));

Cas d'usage : Transformer, copier, geler ou iterer sur les propriétés d'un objet de manière standard.

#core#fondamental

Optional Catch Binding

JavaScript 🟢 Junior

Depuis ES2019, le paramètre du catch est optionnel. Utile quand l'erreur n'est pas nécessaire dans le traitement.

Savoir qu'il y a eu un problème sans avoir besoin de lire le rapport détaillé.

try {
  JSON.parse(input);
} catch {
  // pas besoin de (err)
  return defaultValue;
}

Cas d'usage : Cas ou on veut juste ignorer l'erreur et fournir un fallback sans logger.

#core#ES2019#syntaxe

Optional Chaining

JavaScript 🟢 Junior

Opérateur ?. qui court-circuite a undefined si la valeur a gauche est null/undefined. Fonctionne sur les propriétés, méthodes et accès dynamiques.

Frapper a une porte : si personne ne répond (?.), tu passes ton chemin au lieu de défoncer la porte (TypeError).

const city = user?.address?.city;
const result = obj?.method?.();
const val = arr?.[0]?.name;

Cas d'usage : Accéder a des propriétés de données API incertaines sans multiplier les vérifications if.

Anti-pattern : En abuser sur des chemins qui ne devraient jamais être nullish, masquant des bugs réels.
#core#ES2020#syntaxe

Oxc et Oxlint

JavaScript 🟡 Mid

Oxc (« JavaScript Oxidation Compiler ») est une chaîne d'outils en Rust : parseur, résolveur, transformeur, minifieur, formateur (Oxfmt) et linter (Oxlint). Oxlint embarque plus de 865 règles (ESLint, TypeScript, React, Jest, Vitest) et s'annonce 50 à 100 fois plus rapide qu'ESLint ; son analyse typée s'appuie sur tsgo, le port Go de TypeScript 7. Oxc est le compilateur de Rolldown et donc de Vite 8.

Un scanner d'aéroport qui traite toute la file en quelques secondes, au lieu d'ouvrir chaque valise à la main.

# Installer et lancer
pnpm add -D oxlint
npx oxlint .                 # règles par défaut, très rapide

# Migrer une config ESLint existante
npx @oxlint/migrate

# Cohabiter : ESLint ne garde que ce qu'Oxlint ne couvre pas
pnpm add -D eslint-plugin-oxlint

Cas d'usage : Grands monorepos et CI où ESLint devient le goulot ; pré-commit instantané ; cohérence avec la chaîne Vite/Rolldown.

Anti-pattern : Supprimer ESLint du jour au lendemain alors qu'un plugin maison n'a pas d'équivalent Oxlint : migrer par étapes avec eslint-plugin-oxlint.
#tooling#lint#rust

Partial Application

JavaScript 🟡 Mid

Fixer un ou plusieurs arguments d'une fonction pour créer une nouvelle fonction avec moins de paramètrès. Contrairement au currying, on peut fixer plusieurs arguments d'un coup.

Pre-remplir une partie d'un formulaire : les champs fixes ne changent plus, tu ne remplis que le reste.

const multiply = (a, b) => a * b;
const double = multiply.bind(null, 2);
double(5);  // 10
// Ou sans bind
const partial = (fn, ...fixed) =>
  (...args) => fn(...fixed, ...args);

Cas d'usage : Créer des variantes de fonctions utilitaires (logger avec prefix, requêtes avec base URL).

#core#fonctionnel#pattern

PerformanceObserver

JavaScript 🔴 Senior

API qui observe les entrées de la Performance Timeline (paint, navigation, resource, longtask, etc.). Permet de collecter les métriques Web Vitals de manière non-bloquante.

Un chronomètre automatique qui enregistre les temps de chaque étape d'une course sans que les coureurs s'arrêtent.

const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.log(entry.name, entry.duration);
  });
});
observer.observe({ type: 'largest-contentful-paint',
  buffered: true });

Cas d'usage : Mesurer LCP, FID, CLS en production, monitoring RUM (Real User Monitoring).

#core#performance#monitoring

Private Class Fields

JavaScript 🟡 Mid

Champs de classe préfixes par # véritablement prives (hard private). Non accessibles en dehors de la classe, même par les sous-classes. Contrairement aux conventions _prefix.

Un coffre-fort dans ta chambre : même les membres de ta famille ne peuvent pas l'ouvrir.

class Counter {
  #count = 0;
  increment() { this.#count++; }
  get value() { return this.#count; }
}
const c = new Counter();
c.increment();
c.value;   // 1
// c.#count; // SyntaxError

Cas d'usage : Encapsulation stricte dans les classes, protection des invariants internes.

#core#ES2022#OOP

Promise

JavaScript 🟢 Junior? entretien

Objet représentant le résultat futur d'une opération asynchrone. Peut être pending, fulfilled ou rejected. Chainable via .then() et .catch().

Un ticket de pressing : tu deposes ton vêtement, tu reçois un ticket, et tu reviens le chercher quand c'est prêt (ou on te prévient si c'est perdu).

const getData = () => new Promise((resolve, reject) => {
  setTimeout(() => resolve('data'), 100);
});
getData()
  .then(data => console.log(data))
  .catch(err => console.error(err));

Cas d'usage : Gérer toute opération asynchrone : appels API, lecture de fichiers, timers.

Anti-pattern : Imbriquer les .then() au lieu de les chaîner, recréant un callback hell avec des promesses.
#core#interview#async#fondamental

Promise Error Handling

JavaScript 🟡 Mid

Les rejections de Promise doivent être catchees avec .catch() ou try/catch avec await. Les rejections non gérées déclenchent unhandledrejection et peuvent crasher en Node.js.

Un filet sous le trapèze : sans lui (catch), la moindre chute (rejection) est fatale.

// Avec async/await
try {
  const data = await fetchData();
} catch (err) {
  handleError(err);
}
// Global fallback
window.addEventListener('unhandledrejection', (e) => {
  reportError(e.reason);
});

Cas d'usage : Toute chaîne de promesses doit avoir un catch terminal pour éviter les rejections silencieuses.

Anti-pattern : Chaîne de .then() sans .catch() final, ou catch vide qui avale les erreurs.
#core#async#best-practice

Promise.all / allSettled / race / any

JavaScript 🟡 Mid? entretien

Combinateurs statiques de Promise : all (toutes réussies ou premier échec), allSettled (toutes terminées), race (première terminée), any (première réussie). Deux ajouts récents : Promise.withResolvers (ES2024) qui renvoie {promise, résolve, reject}, et Promise.try (ES2025) qui exécute une fonction synchrone ou asynchrone en capturant ses exceptions dans une promesse.

all = tous les invites doivent arriver pour manger. race = on mange des que le premier arrive. any = on mange des qu'un invite avec le dessert arrive. allSettled = on attend que tout le monde ait répondu, oui ou non.

const [a, b] = await Promise.all([fetchA(), fetchB()]);
const etats = await Promise.allSettled([p1, p2]);
const rapide = await Promise.race([p1, timeout(500)]);
const premier = await Promise.any([p1, p2]);
// ES2024 : résolveurs externes
const { promise, resolve } = Promise.withResolvers();
// ES2025 : capture aussi les throw synchrones
await Promise.try(() => JSON.parse(texte)).catch(console.error);

Cas d'usage : Paralleliser des appels API indépendants (all), tolérant aux échecs (allSettled), timeout (race).

Anti-pattern : Utiliser await en série pour des opérations indépendantes au lieu de Promise.all.
#core#interview#async#performance#ES2025

Promise.try()

JavaScript 🟡 Mid

Méthode statique ES2025 qui appelle une fonction immédiatement et enveloppe son résultat dans une promesse : une valeur renvoyée donne une promesse déjà résolue, un throw synchrone une promesse rejetée, une promesse renvoyée est simplement suivie. Elle unifie ainsi le traitement des callbacks synchrones et asynchrones. Disponible dans les navigateurs majeurs depuis janvier 2025.

Un filet de sécurité tendu avant le saut, que le trapéziste tombe tout de suite ou plus tard.

function executer(action) {
  return Promise.try(action)
    .then(r => console.log('ok', r))
    .catch(e => console.error('erreur', e.message));
}
executer(() => 'sync');                 // ok sync
executer(() => { throw new Error('x'); }); // erreur x (pas de crash)
executer(async () => 'async');         // ok async
// Avant : Promise.resolve().then(fn) retardait fn d'un tick

Cas d'usage : Wrappers de plugins ou de hooks utilisateur dont on ne sait pas s'ils sont async ; débuts de chaînés de promesses.

Anti-pattern : Écrire Promise.résolve(fn()) : un throw synchrone dans fn échappe à la chaîne .catch.
#core#ES2025#async

Promise.withResolvers()

JavaScript 🟡 Mid

Méthode statique ES2024 qui renvoie un objet {promise, résolve, reject} : la promesse et ses fonctions de règlement vivent dans le même scope, sans passer par le constructeur et ses variables externes. Disponible partout depuis mars 2024 (Baseline).

Recevoir la boîte et la clé en même temps, plutôt que de devoir fabriquer la clé depuis l'intérieur de la boîte.

// File d'attente : on résout plus tard, depuis un autre événement
const { promise, resolve, reject } = Promise.withResolvers();
bouton.addEventListener('click', () => resolve('cliqué'), { once: true });
setTimeout(() => reject(new Error('délai')), 5000);
console.log(await promise);

// Avant : let res; const p = new Promise(r => { res = r; });

Cas d'usage : Ponts événement → promesse, files de messages, itérateurs asynchrones alimentés de l'extérieur.

Anti-pattern : Stocker résolve dans une variable globale « pour plus tard » : préférer le trio local et un seul appel.
#core#ES2024#async

Prototypal Inheritance

JavaScript 🟡 Mid? entretien

Modèle d'héritage de JS ou les objets héritent directement d'autres objets via la prototype chain, contrairement a l'héritage classique par classes. Les classes ES6 sont du sucre syntaxique dessus.

Photocopier un document et modifier la copie : l'original reste intact, et tu peux toujours te référer a lui.

function Vehicle(type) { this.type = type; }
Vehicle.prototype.describe = function() {
  return `I am a ${this.type}`;
};
const car = new Vehicle('car');
car.describe(); // 'I am a car'

Cas d'usage : Créer des hiérarchies d'objets légères sans le coût d'un système de classes complet.

#core#interview#OOP

Prototype Chain

JavaScript 🟡 Mid? entretien

Chaîne de prototypes par laquelle JS recherche les propriétés et méthodes. Chaque objet a un [[Prototype]] interne qui pointe vers un autre objet, jusqu'a null.

L'arbre généalogique : si tu ne sais pas cuisiner, tu demandes a ta mère, puis a ta grand-mère, en remontant les générations.

const animal = { eat() { return true; } };
const dog = Object.create(animal);
dog.bark = () => 'Woof';
dog.eat();  // true (remonte la chaine)
dog.bark(); // 'Woof' (propre)

Cas d'usage : Comprendre l'héritage en JS, le fonctionnement de class/extends, et optimiser la recherche de propriétés.

Anti-pattern : Modifier Object.prototype directement, polluant tous les objets de l'application.
#core#interview#OOP

Proxy

JavaScript 🔴 Senior

Objet qui encapsulé un autre objet et intercepte les opérations fondamentales (get, set, has, delete, etc.) via des traps. Base de la réactivité dans Vue 3 et des ORMs modernes.

Un secrétaire personnel qui intercepte tous tes appels et courriers, et peut les modifier avant de te les transmettre.

const handler = {
  get(target, key) {
    console.log(`Reading ${key}`);
    return target[key];
  },
  set(target, key, value) {
    console.log(`Setting ${key}=${value}`);
    target[key] = value;
    return true;
  }
};
const proxy = new Proxy({}, handler);

Cas d'usage : Systèmes réactifs (Vue 3), validation automatique, logging transparent, mocking en tests.

Anti-pattern : Abuser des Proxy en hot path : l'overhead d'interception dégrade les performances.
#core#ES6#avance#pattern

Pure Function

JavaScript 🟢 Junior

Fonction qui retourne toujours le même résultat pour les mêmes arguments et ne produit aucun effet de bord. Déterministe et sans mutation d'état externe.

Une calculatrice : 2+3 donne toujours 5, peu importe quand ou ou tu fais le calcul.

// Pure
const add = (a, b) => a + b;
const upper = (s) => s.toUpperCase();

// Impure
let count = 0;
const increment = () => ++count; // mutation externe

Cas d'usage : Reducers Redux, fonctions de transformation, tests unitaires faciles, memoization possible.

#core#fonctionnel#principe

queueMicrotask

JavaScript 🟡 Mid

Fonction globale qui ajoute un callback a la microtask queue. Plus léger que Promise.résolve().then() pour planifier une microtask.

Glisser un post-it urgent sur la pile 'a traiter immédiatement' au lieu de créer un ticket formel (Promise).

console.log('1');
queueMicrotask(() => console.log('2'));
console.log('3');
// 1, 3, 2

Cas d'usage : Différer une action après le code synchrone courant mais avant le prochain rendu.

Anti-pattern : Utiliser queueMicrotask en boucle recursive, bloquant la macrotask queue indéfiniment.
#core#async

Reflect

JavaScript 🔴 Senior

Objet built-in fournissant des méthodes statiques pour les opérations interceptables par Proxy. Miroir 1:1 des traps de Proxy avec des retours booléens au lieu d'exceptions.

Le mode d'emploi officiel des opérations JS : au lieu de bidouiller, tu utilises la méthode standard.

const obj = { x: 1 };
Reflect.get(obj, 'x');        // 1
Reflect.set(obj, 'y', 2);     // true
Reflect.has(obj, 'x');        // true
Reflect.ownKeys(obj);         // ['x', 'y']

Cas d'usage : Toujours utiliser Reflect dans les traps de Proxy pour le comportement par défaut correct.

#core#ES6#avance

RegExp Modifiers (?i:...)

JavaScript 🟡 Mid

Modificateurs inline standardisés dans ES2025 : (?i:motif), (?m:motif), (?s:motif) activent un drapeau sur une portion seulement, et (?-i:motif) le désactive. Seuls i, m et s sont autorisés ; g, y, u, v et d restent globaux. Disponible dans les navigateurs majeurs depuis septembre 2025 (Baseline 2025).

Un interrupteur local dans une pièce, plutôt que le disjoncteur général de la maison.

// 'hello' insensible à la casse, 'World' sensible
const re = /(?i:hello) World/;
re.test('HELLO World'); // true
re.test('hello world'); // false

// Désactiver m localement dans une regex multi-lignes
const front = /(?-m:^)---\n^title:.*$/ms;

Cas d'usage : Grammaires, lexers, validations où une seule partie du motif doit ignorer la casse.

Anti-pattern : Dupliquer la regex en deux variantes (avec et sans i) : les modificateurs évitent la duplication.
#core#ES2025#regex

RegExp.escape()

JavaScript 🟢 Junior

Méthode statique (ES2025) qui échappe tous les caractères spéciaux d'une chaîne afin de l'insérer telle quelle dans un motif construit avec new RegExp. Elle protège aussi les ponctuations et le premier caractère alphanumérique (\x66oo). Disponible dans les navigateurs majeurs depuis mai 2025 (Baseline 2025) ; ajoutée aux types TypeScript en 6.0.

Mettre des guillemets autour d'une recherche Google pour qu'elle soit prise au mot.

const domaine = 'developer.mozilla.org';
// Sans escape, le point matche n'importe quel caractère
const re = new RegExp(`https?://${RegExp.escape(domaine)}(?=/)`, 'g');
re.test('https://developer.mozilla.org/fr'); // true
re.test('https://developerXmozilla.org/fr'); // false
RegExp.escape('a+b?'); // '\\x61\\+b\\?'

Cas d'usage : Recherche utilisateur injectée dans une regex, filtres dynamiques, remplacement littéral.

Anti-pattern : Copier un utilitaire escapeRegExp fait maison qui oublie un caractère : la version native couvre le jeu complet.
#core#ES2025#securite

requestAnimationFrame

JavaScript 🟡 Mid

API qui planifie un callback avant le prochain repaint du navigateur (~60fps). Synchronise les animations avec le cycle de rendu pour des animations fluides.

Attendre le signal du métronome avant de jouer la note suivante : tout reste synchronise avec le rythme d'affichage.

function animate(timestamp) {
  element.style.transform =
    `translateX(${timestamp / 10}px)`;
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

Cas d'usage : Animations JS fluides, canvas rendering, synchronisation avec le cycle de repaint.

Anti-pattern : Utiliser setInterval pour les animations : desynchronise du rendu, gaspille des frames.
#core#performance#animation

requestIdleCallback

JavaScript 🔴 Senior

API qui planifie un callback pendant les périodes d'inactivité du navigateur. Reçoit un IdleDeadline indiquant le temps restant. Idéal pour les taches non-urgentes.

Faire le ménage pendant les pubs a la télé : tu profites des pauses naturelles sans interrompre le programme.

requestIdleCallback((deadline) => {
  while (deadline.timeRemaining() > 0 && tasks.length) {
    processTask(tasks.pop());
  }
  if (tasks.length) requestIdleCallback(cb);
}, { timeout: 2000 });

Cas d'usage : Analytics, prefetching, taches de fond non-critiques, warm-up de cache.

#core#performance

require(esm)

JavaScript 🟡 Mid

Capacité de Node.js à charger un module ESM depuis CommonJS avec require(). Ajoutée en 22.0.0 et 20.17.0 derrière un drapeau, activée par défaut en 22.12.0 et 20.19.0, elle est stable depuis 25.4.0. Condition : le module ESM ne doit pas contenir de top-level await (sinon ERR_REQUIRE_ASYNC_MODULE). TypeScript 5.8 (28 février 2025) la modélise avec --module nodenext.

Une porte enfin percée entre deux immeubles mitoyens : on passe d'un côté à l'autre sans faire le tour du pâté de maisons.

// utils.mjs
export function slug(s) { return s.toLowerCase().replace(/\s+/g, '-'); }

// legacy.cjs — Node 22.12+/20.19+
const { slug } = require('./utils.mjs');
console.log(slug('Hello World')); // hello-world
// Détection : process.features.require_module === true
// Diagnostic d'un TLA bloquant : --experimental-print-required-tla

Cas d'usage : Consommer une dépendance publiée en ESM seul depuis une base CommonJS ; simplifier la publication des bibliothèques.

Anti-pattern : Ajouter un top-level await dans un module destiné à être requis : il devient inaccessible à require().
#core#modules#node22#node25

ResizeObserver

JavaScript 🟡 Mid

API qui observe les changements de taille d'un élément DOM. Appelle le callback quand les dimensions changent, sans dépendre du resize de la fenêtre.

Un mètre automatique colle sur un meuble qui t'alerte des que les dimensions changent.

const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect;
    console.log(`${width}x${height}`);
  }
});
observer.observe(document.querySelector('.chart'));

Cas d'usage : Graphiques responsifs, conteneurs flexibles, composants qui s'adaptent a leur taille.

#core#DOM#responsive

Scope Chain

JavaScript 🟡 Mid? entretien

Chaîne de références entre les scopes imbriques qui permet a une fonction d'accéder aux variables de ses scopes parents. La recherche remonte la chaîne jusqu'au scope global.

Chercher un livre dans ta chambre, puis le salon, puis la bibliothèque municipale : tu remontes les niveaux jusqu'a trouver.

const global = 'G';
function outer() {
  const mid = 'M';
  function inner() {
    const local = 'L';
    console.log(global, mid, local); // G M L
  }
  inner();
}

Cas d'usage : Comprendre la résolution des variables et éviter les collisions de noms entre scopes imbriques.

#core#interview#fondamental

Service Workers

JavaScript 🔴 Senior

Proxy programmable entre l'app et le réseau, tournant en arrière-plan. Intercepte les requêtes fetch pour implémenter du cache offline, des push notifications et la synchronisation en arrière-plan.

Un concierge d'hôtel qui intercepte ton courrier : il peut te le remettre du stock (cache) sans appeler le facteur (réseau).

// sw.js
self.addEventListener('fetch', (e) => {
  e.respondWith(
    caches.match(e.request)
      .then(cached => cached || fetch(e.request))
  );
});
// Registration
navigator.serviceWorker.register('/sw.js');

Cas d'usage : PWA offline-first, cache intelligent, push notifications, background sync.

Anti-pattern : Cacher agressivement sans stratégie d'invalidation, affichant des données périmées a l'infini.
#core#PWA#performance#navigateur

Set

JavaScript 🟢 Junior

Collection de valeurs uniques, itérable et ordonnée par insertion ; un doublon ajouté est ignoré. ES2025 a ajouté sept méthodes ensemblistes : union, intersection, différence, symmetricDifference, isSubsetOf, isSupersetOf et isDisjointFrom, disponibles dans tous les navigateurs majeurs depuis juin 2024 (Baseline 2024).

Un tampon encreur qui marque les invites a l'entrée : même si tu te représentes, tu n'es compte qu'une fois.

const a = new Set([1, 2, 2, 3]); // Set {1, 2, 3}
a.has(2); // true
[...new Set(tableau)]; // dédoublonnage
// ES2025
const b = new Set([3, 4]);
a.union(b);        // Set {1, 2, 3, 4}
a.intersection(b); // Set {3}
a.isDisjointFrom(new Set([9])); // true

Cas d'usage : Deduplication de tableaux, tracking d'éléments uniques, vérification d'appartenance O(1).

#core#ES6#ES2025#performance

Set Methods (ES2025)

JavaScript 🟢 Junior? entretien

Sept méthodes ensemblistes ajoutées à Set par ES2025 : union, intersection, différence, symmetricDifference, isSubsetOf, isSupersetOf et isDisjointFrom. Elles renvoient un nouveau Set (ou un booléen) et acceptent tout objet « set-like » exposant size, has et keys. Disponibles dans tous les navigateurs majeurs depuis juin 2024 (Baseline 2024) et dans TypeScript depuis la 5.5.

Les diagrammes de Venn du collège, enfin disponibles en une ligne.

const admins = new Set(['ana', 'bob']);
const actifs = new Set(['bob', 'chloe']);
admins.union(actifs);               // Set {ana, bob, chloe}
admins.intersection(actifs);        // Set {bob}
admins.difference(actifs);          // Set {ana}
admins.symmetricDifference(actifs); // Set {ana, chloe}
new Set(['bob']).isSubsetOf(admins); // true
admins.isDisjointFrom(new Set(['zoe'])); // true

Cas d'usage : Droits d'accès, comparaison de tags, détection de doublons entre deux listes sans boucles manuelles.

Anti-pattern : Réécrire ces opérations avec filter + has : plus long, plus lent, et moins lisible.
#core#ES2025#interview

SharedArrayBuffer

JavaScript 🔴 Senior

ArrayBuffer partageable entre le thread principal et les Web Workers. Permet la mémoire partagée mais nécessite des Atomics pour éviter les race conditions.

Un tableau blanc partage entre collègués : tout le monde peut écrire dessus, mais il faut un protocole pour ne pas se marcher dessus.

const sab = new SharedArrayBuffer(1024);
const arr = new Int32Array(sab);
// Envoyer au worker
worker.postMessage(sab);
// Dans le worker : meme memoire

Cas d'usage : Calculs parallèles lourds entre workers, applications temps réel, WASM multithread.

Anti-pattern : Lire/écrire sans Atomics : race conditions et données corrompues.
#core#avance#performance

SharedWorker

JavaScript 🔴 Senior

Worker partage entre plusieurs contextes de navigation (onglets, iframes) de la même origine. Communique via des ports MessagePort. Un seul thread pour tous les onglets.

Un serveur de chat partage : tous les onglets du même site se connectent au même salon.

// shared.js
onconnect = (e) => {
  const port = e.ports[0];
  port.onmessage = (ev) => {
    port.postMessage(`Echo: ${ev.data}`);
  };
};
// page.js
const sw = new SharedWorker('shared.js');
sw.port.postMessage('hello');

Cas d'usage : État partage entre onglets, connexion WebSocket unique, cache multi-onglets.

#core#avance#navigateur

Side Effect

JavaScript 🟢 Junior

Toute modification d'état observable en dehors de la fonction : mutation de variable globale, écriture DOM, appel réseau, console.log, modification d'arguments. L'oppose d'une pure function.

Laisser des miettes sur la table en mangeant : tu as fait ton action (manger) mais tu as aussi change l'environnement.

// Side effects
let total = 0;
function addToTotal(n) {
  total += n;        // mutation globale
  console.log(total); // I/O
  document.title = n; // DOM
}

Cas d'usage : Nécessaires en pratique (I/O, DOM, API), mais a isoler et contrôler dans des couches dédiées.

#core#fonctionnel#principe

Side Effects in Modules

JavaScript 🔴 Senior

Code exécuté a l'import d'un module (polyfills, CSS imports, enregistrement global). Le champ sideEffects dans package.json indique au bundler quels fichiers ont des effets de bord.

Un colis piège : juste en l'ouvrant (import), quelque chose se déclenche automatiquement.

// polyfill.js (side effect)
import 'core-js/stable';

// package.json
{
  "sideEffects": ["*.css", "./src/polyfills.js"]
}
// false = aucun side effect, tree shaking total

Cas d'usage : Déclarer correctement sideEffects pour permettre un tree shaking optimal par le bundler.

Anti-pattern : Mettre sideEffects: false quand le module a vraiment des effets de bord (CSS, polyfills).
#core#modules#performance

Spread / Rest

JavaScript 🟢 Junior

L'opérateur ... sert de spread (étaler un iterable) ou rest (collecter les arguments restants). Spread copie superficiellement, rest regroupe dans un tableau.

Spread = étaler les cartes sur la table. Rest = ramasser toutes les cartes restantes en un paquet.

// Spread
const merged = { ...obj1, ...obj2 };
const copy = [...array];
// Rest
function sum(...nums) {
  return nums.reduce((a, b) => a + b, 0);
}

Cas d'usage : Copier/fusionner objets et tableaux de manière immutable, collecter des arguments variadiques.

Anti-pattern : Croire que spread fait une copie profonde (deep clone) : les objets imbriques restent par référence.
#core#ES6#syntaxe

stopPropagation empêche l'evenement de remonter/descendre aux parents mais exécute les autres listeners du même élément. stopImmediatePropagation arrête aussi les listeners suivants sur le même élément.

stopPropagation = fermer la porte de ta chambre (les voisins n'entendent plus). stopImmediate = aussi couper le son dans ta chambre (même toi tu n'entends plus).

el.addEventListener('click', (e) => {
  e.stopPropagation(); // parent ne recoit pas
});
el.addEventListener('click', (e) => {
  e.stopImmediatePropagation();
  // les listeners suivants sur el sont aussi stoppes
});

Cas d'usage : Empêcher un modal de se fermer quand on clique a l'intérieur, isoler des composants.

Anti-pattern : Utiliser stopPropagation partout, cassant l'event délégation et le tracking analytics.
#core#DOM

Streams API

JavaScript 🔴 Senior

API pour traiter des données en flux (ReadableStream, WritableStream, TransformStream). Permet de consommer des données chunk par chunk sans tout charger en mémoire.

Un tuyau d'arrosage : l'eau (données) coule en continu au lieu d'être livrée en citerne entière.

const response = await fetch('/big-file');
const reader = response.body.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  process(value); // Uint8Array chunk
}

Cas d'usage : Télécharger des gros fichiers avec progression, streaming SSE/LLM, traitement vidéo/audio.

#core#avance#performance

Strict Mode

JavaScript 🟢 Junior

Mode d'exécution plus strict active par 'use strict' ou implicitement dans les modules ESM. Interdit les variables non déclarées, les doublons de params, et rend this undefined dans les fonctions simples.

Le mode examen : plus de copier-coller, plus de brouillon, chaque erreur est signalée immédiatement.

'use strict';
x = 5;         // ReferenceError
delete Object.prototype; // TypeError
function f() { return this; } // undefined

Cas d'usage : Actif par défaut dans les modules ESM et les classes. Attrape les erreurs silencieuses tôt.

#core#fondamental

Structured Clone

JavaScript 🟡 Mid

API globale structuredClone() qui crée une copie profonde d'un objet, supportant les types complexes (Date, Map, Set, ArrayBuffer, etc.). Remplace JSON.parse(JSON.stringify()).

Une photocopieuse couleur haute fidélité qui reproduit chaque détail, contrairement a une photocopie noir et blanc (JSON).

const original = {
  date: new Date(),
  data: new Map([['a', 1]]),
  nested: { arr: [1, 2] }
};
const clone = structuredClone(original);
clone.nested.arr.push(3);
// original.nested.arr inchange

Cas d'usage : Deep clone d'états complexes, transfert de données entre workers, copie d'objets avec types spéciaux.

Anti-pattern : Utiliser JSON.parse(JSON.stringify(obj)) qui perd les Date, Map, Set, undefined et les fonctions.
#core#ES2022#performance

structuredClone vs JSON

JavaScript 🟡 Mid

JSON.parse(JSON.stringify()) perd les Date, Map, Set, undefined, fonctions et références circulaires. structuredClone gère tout sauf les fonctions et le DOM. Toujours préférer structuredClone.

JSON = scanner un document en noir et blanc (perd les couleurs). structuredClone = photocopier en couleur haute fidélité.

const obj = { d: new Date(), m: new Map([['a',1]]) };
// JSON perd tout
JSON.parse(JSON.stringify(obj));
// { d: '2024-...', m: {} }
// structuredClone preserve
structuredClone(obj);
// { d: Date, m: Map }

Cas d'usage : Deep clone d'états complexes avec des types non-JSON.

#core#best-practice

Symbol

JavaScript 🟡 Mid

Type primitif unique et immutable créé par Symbol(). Utilise comme clé de propriété pour éviter les collisions. Les well-known symbols (Symbol.iterator, etc.) customisent le comportement du langage.

Un numéro de série unique grave sur une clé : même si deux clés se ressemblent, leurs numéros sont différents.

const id = Symbol('id');
const user = { [id]: 123, name: 'Alice' };
user[id]; // 123
Object.keys(user); // ['name'] (symbol invisible)
// Well-known
class Range {
  *[Symbol.iterator]() { yield 1; yield 2; }
}

Cas d'usage : Créer des propriétés privées-like, définir des protocoles (iterator), éviter les collisions de noms en libs.

#core#ES6#avance

Tagged Templates

JavaScript 🔴 Senior

Fonction appelée avec un template literal comme argument. Reçoit les parties statiques et les valeurs interpolées séparément, permettant un traitement personnalise.

Un traducteur qui reçoit la phrase avec des trous et les mots a insérer, et peut modifier chaque mot avant de reconstruire la phrase.

function highlight(strings, ...values) {
  return strings.reduce((acc, str, i) =>
    `${acc}${str}<b>${values[i] ?? ''}</b>`, '');
}
const name = 'Alice';
highlight`Hello ${name}!`;
// 'Hello <b>Alice</b>!'

Cas d'usage : Sanitisation HTML (lit-html), CSS-in-JS (styled-components), SQL sécurisé, i18n.

#core#avance#pattern

Pattern ou un champ commun (type, kind) distingue les variantes d'un objet. Permet un pattern matching exhaustif et du code type-safe. Fondamental en TypeScript.

Des colis avec une étiquette de couleur : bleu = fragile, rouge = urgent. L'étiquette déterminé le traitement.

function handle(action) {
  switch (action.type) {
    case 'add': return state + action.value;
    case 'reset': return 0;
    default: throw new Error(`Unknown: ${action.type}`);
  }
}
handle({ type: 'add', value: 5 });

Cas d'usage : Reducers Redux, state machines, gestion d'evenements, API responses.

#core#pattern#architecture

Task Queue

JavaScript 🟡 Mid

Terme générique pour la file de macrotasks (setTimeout, setInterval, I/O). Synonyme de Callback Queue dans la spec HTML. Un seul macrotask est traite par tour d'event loop.

La liste des corvées a faire une par une : après chaque corvée, tu vérifies s'il y a un message urgent (microtask).

// Un macrotask par tour de boucle
setTimeout(() => console.log('task 1'), 0);
setTimeout(() => console.log('task 2'), 0);
// Entre task 1 et task 2, les microtasks sont videes

Cas d'usage : Décomposer un traitement lourd en petits morceaux via setTimeout pour ne pas bloquer le thread principal.

#core#async

Template Literals

JavaScript 🟢 Junior

Chaînés délimitées par des backticks (`) supportant l'interpolation ${expression}, le multi-ligne et les tagged templates. Remplacent la concatenation classique.

Un formulaire avec des champs a remplir : les ${} sont les cases vides ou JS inséré les valeurs.

const name = 'World';
const greeting = `Hello, ${name}!`;
const multiline = `
  Line 1
  Line 2
`;

Cas d'usage : Construire des chaînés dynamiques, des requêtes SQL paramétrées (via tagged templates), du HTML.

#core#ES6#syntaxe

Temporal

JavaScript 🟡 Mid? entretien

API de dates et heures conçue pour remplacer Date : objets immuables, fuseaux horaires explicites, précision à la nanoseconde, calendriers multiples. La proposition est au Stage 4 et figure dans la liste TC39 des propositions attendues pour ES2027. Elle est livrée dans Firefox 139 (27 mai 2025), Chrome 144 (13 janvier 2026) et Node.js 26 (5 mai 2026) ; Safari est encore en développement.

Un agenda qui sait qu'un rendez-vous à 9 h à Paris n'est pas à 9 h à Tokyo, au lieu d'une simple horloge murale.

// Node 26+, Chrome 144+, Firefox 139+
const maintenant = Temporal.Now.instant();
const date = Temporal.PlainDate.from('2026-09-27');
const rdv = date.toPlainDateTime('14:30')
  .toZonedDateTime('Europe/Paris');
const dans30j = rdv.add({ days: 30 });   // immuable : nouvel objet
const duree = rdv.until(dans30j);         // Temporal.Duration
console.log(duree.days);                  // 30

Cas d'usage : Réservations, facturation, planification multi-fuseaux : partout où Date et ses décalages implicites causent des bugs.

Anti-pattern : Mélanger Temporal et Date dans une même logique métier : convertir une seule fois aux frontières (toTemporalInstant / epochMilliseconds).
#core#ES2027#node26#interview

Temporal Dead Zone

JavaScript 🟡 Mid? entretien

Zone entre le début du scope et la déclaration let/const ou la variable existe mais est inaccessible. Toute tentative d'accès lance un ReferenceError.

Un colis en transit : il a été expédié (hoiste) mais tu ne peux pas l'ouvrir tant qu'il n'est pas livre (déclaration).

{
  // TDZ pour x commence ici
  console.log(x); // ReferenceError!
  // TDZ pour x finit ici
  let x = 42;
  console.log(x); // 42
}

Cas d'usage : Comprendre pourquoi let/const est plus sur que var et debugger les ReferenceError.

#core#interview#fondamental

this keyword

JavaScript 🟡 Mid? entretien

Référence au contexte d'exécution courant. Sa valeur dépend de comment la fonction est appelée : méthode (objet), constructeur (nouvelle instance), arrow function (this lexical), ou appel simple (undefined en strict).

Le pronom 'je' : sa signification change selon qui parle, pas selon ou la phrase est écrite.

const obj = {
  name: 'Alice',
  greet() { return this.name; },       // 'Alice'
  arrow: () => this.name,               // undefined (this lexical)
};
const fn = obj.greet;
fn(); // undefined (contexte perdu)

Cas d'usage : Accéder aux propriétés de l'objet courant dans les méthodes de classe ou les callbacks.

Anti-pattern : Passer une méthode comme callback sans bind, perdant le contexte this.
#core#interview#fondamental

Throttle

JavaScript 🟡 Mid? entretien

Limite l'exécution d'une fonction a maximum une fois par intervalle de temps. Contrairement au debounce, garantit une exécution régulière pendant une rafale d'appels.

Un robinet a débit contrôle : même si tu l'ouvres a fond, l'eau coule toujours a la même vitesse.

function throttle(fn, ms) {
  let last = 0;
  return function(...args) {
    const now = Date.now();
    if (now - last >= ms) {
      last = now;
      fn.apply(this, args);
    }
  };
}

Cas d'usage : Scroll handler, mousemove tracking, rate limiting d'appels API cote client.

#core#performance#pattern#interview

Top-level Await

JavaScript 🟡 Mid

Permet d'utiliser await directement au niveau module (ESM) sans wrapper async. Le module devient asynchrone et les modules qui l'importent attendent sa résolution.

Pouvoir commander directement au drive-in sans devoir d'abord entrer dans le restaurant (la fonction async).

// config.mjs (ESM)
const res = await fetch('/config.json');
export const config = await res.json();

// app.mjs
import { config } from './config.mjs';
// config est deja resolue ici

Cas d'usage : Charger une configuration ou initialiser une connexion BD au démarrage d'un module ESM.

Anti-pattern : L'utiliser dans un module importe par beaucoup d'autres : ca bloque le chargement de tous les dépendants.
#core#ES2022#modules

Transducer

JavaScript 🔴 Senior

Transformations composables et indépendantes du type de collection. Combine map, filter, reduce en un seul passage sans créer de tableaux intermédiaires.

Un ouvrier polyvalent sur une chaîne de montage qui fait tri + transformation + emballage en un seul passage au lieu de trois passages séparés.

const map = f => step => (acc, x) => step(acc, f(x));
const filter = pred => step => (acc, x) =>
  pred(x) ? step(acc, x) : acc;
const xform = [filter(x => x % 2), map(x => x * 10)];
const transduce = xform.reduceRight(
  (s, fn) => fn(s), (acc, x) => [...acc, x]
);

Cas d'usage : Traitement de grands jeux de données en un seul passage, éviter les allocations intermédiaires.

#core#fonctionnel#avance#performance

Tree Shaking

JavaScript 🟡 Mid

Élimination du code mort par les bundlers grâce à l'analyse statique des imports ESM : seuls les exports réellement importés restent dans le bundle. Outils actuels : Rollup, esbuild, webpack et Rolldown, le bundler Rust qui remplace le duo esbuild + Rollup dans Vite 8 (12 mars 2026) avec des builds annoncés 10 à 30 fois plus rapides.

Secouer un arbre pour ne garder que les fruits murs (code utilise) et laisser tomber les feuilles mortes (code inutilisé).

// utils.js
export const used = () => 'kept';
export const unused = () => 'removed';

// app.js
import { used } from './utils';
// unused est elimine du bundle

Cas d'usage : Réduire la taille des bundles en production, surtout avec de grosses librairies comme lodash.

Anti-pattern : import * as lib ou re-exports via barrel files qui empêchent le tree shaking.
#core#performance#modules#vite8

Node.js exécute directement un fichier .ts en effaçant les annotations de type sans les vérifier. Activé par défaut depuis 23.6.0 et 22.18.0, déclaré stable en 25.2.0 et 24.12.0 ; Node 26 supprime --expérimental-transform-types. Seule la syntaxe effaçable passe : enum, namespace avec code, propriétés de paramètre, import = et décorateurs lèvent ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX. L'option TypeScript --erasableSyntaxOnly garantit la compatibilité.

Un correcteur qui gomme les annotations au crayon avant de rendre la copie, sans relire le fond.

// serveur.ts — lancé par : node serveur.ts (Node 24.12+/25.2+)
import type { IncomingMessage } from 'node:http'; // 'type' obligatoire
import { createServer } from 'node:http';

const port: number = 3000;
createServer((req: IncomingMessage, res) => {
  res.end(`ok ${req.url}`);
}).listen(port);
// Interdit ici : enum, namespace avec code, constructor(private x)

Cas d'usage : Scripts, outils internes et serveurs simples en TypeScript sans étape de build ; tsc reste utile pour vérifier les types en CI.

Anti-pattern : Importer un type sans le mot-clé type : l'import survit à l'effacement et échoue à l'exécution.
#core#node24#node26#tooling

Uint8Array Base64 / Hex

JavaScript 🟡 Mid

Proposition Stage 4 (listée par TC39 pour ES2026) qui ajoute Uint8Array.fromBase64, toBase64, fromHex, toHex et setFromBase64 : conversion directe entre octets et texte, sans passer par btoa/atob et leurs chaînés binaires. Options : alphabet 'base64' ou 'base64url', omitPadding. Disponible dans les navigateurs majeurs depuis septembre 2025 (Baseline 2025).

Un adaptateur de prise universel : les octets voyagent en texte sans bricolage.

const octets = new Uint8Array([29, 233, 101, 161]);
octets.toBase64();                        // 'HelloQ=='
octets.toBase64({ alphabet: 'base64url', omitPadding: true }); // 'HelloQ'
octets.toHex();                           // '1de965a1'
Uint8Array.fromBase64('HelloQ==');        // Uint8Array(4)
// Avant : btoa(String.fromCharCode(...octets)) — fragile et lent

Cas d'usage : Jetons dans une URL, clés WebCrypto, transport binaire en JSON, empreintes hexadécimales.

Anti-pattern : Encoder du texte UTF-8 avec btoa directement : il ne gère que les caractères Latin-1 ; passer par TextEncoder puis toBase64.
#core#ES2026#binaire

V8 Hidden Classes

JavaScript 🔴 Senior

Structure interne de V8 pour optimiser l'accès aux propriétés. Les objets avec la même forme (mêmes propriétés, même ordre) partagent une hidden class, permettant un accès rapide.

Des formulaires pre-imprimes identiques : si tout le monde remplit les mêmes champs dans le même ordre, le traitement est ultra rapide.

// Meme hidden class (optimise)
function Point(x, y) { this.x = x; this.y = y; }
const p1 = new Point(1, 2);
const p2 = new Point(3, 4);
// Hidden class differente (desoptimise)
const a = {}; a.x = 1; a.y = 2;
const b = {}; b.y = 2; b.x = 1; // ordre different!

Cas d'usage : Écrire du code monomorphique pour maximiser les optimisations JIT de V8.

Anti-pattern : Ajouter des propriétés dynamiquement dans un ordre différent ou supprimer des propriétés avec delete.
#core#engine#performance

Vite 8 et Rolldown

JavaScript 🟡 Mid

Vite 8 (12 mars 2026) remplace le duo esbuild (développement) + Rollup (production) par Rolldown, bundler écrit en Rust et compatible avec l'API des plugins Rollup, épaulé par le compilateur Oxc pour parser, transformer et minifier. Gains annoncés : builds 10 à 30 fois plus rapides (Linear : 46 s → 6 s). Node.js 20.19+ ou 22.12+ requis ; Vite 8.1 est sorti le 23 juin 2026.

Remplacer deux moteurs de marques différentes par un seul bloc : moins de pièces, mêmes commandes.

// vite.config.js — même API, moteur Rolldown
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    rolldownOptions: {          // remplace rollupOptions
      output: { manualChunks: { vendor: ['react', 'react-dom'] } },
    },
  },
});
// Chemins tsconfig « paths » résolus nativement, sans plugin

Cas d'usage : Applications front (React, Vue, Svelte…), SSR, bibliothèques : la chaîne de build la plus répandue de l'écosystème.

Anti-pattern : Garder des plugins qui manipulent l'AST via des hooks esbuild spécifiques : ils n'existent plus dans Vite 8.
#tooling#bundler#vite8

WeakMap

JavaScript 🔴 Senior

Map dont les clés sont obligatoirement des objets et sont tenues faiblement : si plus aucune référence forte n'existe vers la clé, l'entrée est garbage-collectée. Non iterable.

Des post-it colles sur des objets : quand l'objet part a la poubelle, le post-it disparaît avec.

const metadata = new WeakMap();
let user = { name: 'Alice' };
metadata.set(user, { visits: 0 });
// user = null -> l'entree est GC-ee

Cas d'usage : Stocker des metadonnees privées sur des objets sans empêcher leur garbage collection.

Anti-pattern : Essayer d'iterer une WeakMap ou compter ses éléments (impossible by design).
#core#ES6#avance#performance

WeakRef

JavaScript 🔴 Senior

Référence faible vers un objet qui n'empêche pas sa garbage collection. Accès via .deref() qui retourne l'objet ou undefined s'il a été GC.

Prendre une photo d'un objet au lieu de le garder : tu peux regarder la photo, mais l'objet peut avoir été jeté entre-temps.

let obj = { data: 'important' };
const ref = new WeakRef(obj);
obj = null; // eligible au GC
// Plus tard
const derefed = ref.deref();
if (derefed) console.log(derefed.data);
else console.log('GC collected');

Cas d'usage : Caches non-bloquants, observateurs légers, références optionnelles a des objets DOM.

Anti-pattern : Utiliser WeakRef pour la logique métier critique : le timing du GC est non-déterministe.
#core#avance#ES2021

WeakSet

JavaScript 🔴 Senior

Set dont les valeurs sont obligatoirement des objets tenus faiblement. Non iterable, non denombraable. Utile pour marquer des objets sans empêcher leur GC.

Une liste noire invisible : tu sais si quelqu'un y est, mais tu ne peux pas la consulter en entier.

const visited = new WeakSet();
function process(obj) {
  if (visited.has(obj)) return;
  visited.add(obj);
  // traitement...
}

Cas d'usage : Détecter les références circulaires, marquer les noeuds DOM déjà traites.

#core#ES6#avance

Web Sockets API

JavaScript 🟡 Mid

API de communication bidirectionnelle persistante entre client et serveur via le protocole ws://. Permet l'envoi et la réception de messages en temps réel sans polling.

Un téléphone : une fois la ligne ouverte, les deux cotes peuvent parler quand ils veulent, sans raccrocher et rappeler.

const ws = new WebSocket('wss://api.example.com');
ws.onopen = () => ws.send('Hello');
ws.onmessage = (e) => console.log(e.data);
ws.onerror = (e) => console.error(e);
ws.onclose = () => console.log('Closed');

Cas d'usage : Chat en temps réel, notifications live, trading, jeux multijoueur, dashboards temps réel.

Anti-pattern : Utiliser WebSocket pour des requêtes request/response classiques ou REST suffit.
#core#async#navigateur

Web Workers

JavaScript 🟡 Mid

API permettant d'exécuter du JS dans un thread sépare du thread principal. Communiquent via postMessage/onmessage. N'ont pas accès au DOM.

Un assistant dans un bureau sépare : tu lui envoies du travail par pneumatique (postMessage), il te renvoie le résultat.

// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: bigArray });
worker.onmessage = (e) => console.log(e.data);
// worker.js
onmessage = (e) => {
  const result = heavyCompute(e.data);
  postMessage(result);
};

Cas d'usage : Calculs lourds (crypto, parsing), traitement d'images, opérations qui bloqueraient le thread UI.

Anti-pattern : Créer un worker pour chaque petite opération : le coût de création et de communication dépassé le gain.
#core#performance#navigateur