JavaScript — Cheat Sheet

Tag: javascript, es6, event-loop, closures, promises, async, typescript

Livello: intermedio

TL;DR: Fondamenti del runtime, asincronia (microtask vs macrotask), scope, prototipi e feature moderne di ECMAScript per colloqui tecnici.

Concetti chiave

Motore single-threaded basato su call stack singolo, heap della memoria e loop di eventi.

Event loop gestisce l'esecuzione asincrona tramite call stack, microtask queue e macrotask queue.

Microtask queue (Promise callbacks, queueMicrotask) ha priorita assoluta sul macrotask queue (setTimeout, setInterval).

Closures: una funzione mantiene l'accesso al proprio lexical scope anche dopo l'uscita dallo scope esterno.

Hoisting: dichiarazioni di funzione e var sono sollevate in fase di compilazione; let e const risiedono nella Temporal Dead Zone.

Ereditarieta prototipale: ogni oggetto ha un puntatore interno [[Prototype]] collegato a un altro oggetto o a null.

Binding di this: determinato dal call-site (default, implicito con oggetto, esplicito con call/apply/bind, o new).

Arrow functions: non creano un proprio this, arguments, super o new.target; ereditano this lessicalmente.

Immutabilita: Object.freeze() blocca solo il primo livello; per strutture nidificate serve una copia profonda.

Primitive types: string, number, bigint, boolean, undefined, symbol, null (passati per valore, gli oggetti per riferimento).

Domande tipiche e risposte pronte

Q: Qual e la differenza tra == e ===?R: == esegue una conversione di tipo implicita prima del confronto, mentre === verifica identita di valore e tipo senza coercion.

Q: Come funziona l'Event Loop in JavaScript?R: Esegue il codice sincrono sul call stack, poi svuota completamente i microtask pendenti prima di processare un macrotask alla volta.

Q: Cosa si intende per Temporal Dead Zone (TDZ)?R: Il periodo tra l'ingresso nello scope del blocco e la dichiarazione effettiva della variabile let o const, in cui l'accesso genera ReferenceError.

Q: Qual e la differenza principale tra call, apply e bind?R: call invoca subito la funzione passando argomenti separati, apply la invoca accettando un array, mentre bind restituisce una nuova funzione con il contesto fissato.

Q: Come gestisci la concorrenza asincrona con Promise?R: Uso Promise.all se fallire al primo errore e accettabile, oppure Promise.allSettled se devo ottenere l'esito di ogni operazione indipendente.

Insidie e errori comuni

typeof null restituisce "object" per un bug storico mai rimosso del linguaggio.

0.1 + 0.2 === 0.3 restituisce false a causa della rappresentazione floating point a 64 bit (IEEE 754).

Cattura dell'indice nei cicli for con var invece di let all'interno di callback asincroni.

Dimenticare che async restituisce sempre una Promise, anche restituendo un valore primitivo diretto.

Modifica accidentale dello stato condiviso a causa di shallow copy tramite Object.assign o spread operator su oggetti nidificati.

Snippet e comandiJavaScript

// Esecuzione microtask vs macrotask
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Output: 1, 4, 3, 2

JavaScript

// Implementazione essenziale di un debounce
function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

Da ripassare

[ ] Meccanica interna di generatori e iteratori (Symbol.iterator)

[ ] Dettagli e differenze di garbage collection (Mark-and-Sweep)

[x] Differenza tra shallow copy e deep copy con structuredClone

[x] Sintassi e utilizzo di optional chaining ?. e nullish coalescing ??

Jarvis Interviews
Jarvis