Skip to content

Instantly share code, notes, and snippets.

@arturmamedov
Created September 24, 2025 11:29
Show Gist options
  • Save arturmamedov/690cb2474ea5bb368bee1f8ee942dba1 to your computer and use it in GitHub Desktop.
Save arturmamedov/690cb2474ea5bb368bee1f8ee942dba1 to your computer and use it in GitHub Desktop.

Caso 1

1. Programmazione/Sviluppo Web (Teorico)

Domanda: Spiega la differenza tra frontend e backend nello sviluppo web e fai un esempio di tecnologie utilizzate per ciascuno.

Risposta: Il frontend è la parte dell'applicazione web che l'utente vede e con cui interagisce (interfaccia utente), sviluppato con HTML, CSS e JavaScript. Il backend è la parte server che gestisce logica, database e sicurezza, sviluppato con linguaggi come PHP, Python, Node.js. Esempio: un e-commerce dove il frontend mostra i prodotti e il backend gestisce ordini e pagamenti.

2. HTML

Domanda: Qual è la differenza tra tag semantici e tag generici? Fai esempi di entrambi.

Risposta: I tag semantici hanno un significato specifico e descrivono il contenuto (<header>, <nav>, <article>, <footer>), migliorando SEO e accessibilità. I tag generici come <div> e <span> non hanno significato semantico e servono solo per strutturare o stilizzare il contenuto.

3. CSS

Domanda: Cosa significa "mobile-first" nel CSS responsive e perché è considerato una best practice?

Risposta: Mobile-first significa progettare prima per schermi piccoli, poi aggiungere stili per schermi più grandi usando media query con min-width. È una best practice perché la maggioranza del traffico web è mobile, migliora le performance (si caricano meno stili inizialmente) e garantisce un'esperienza utente ottimale su tutti i dispositivi.

4. Bootstrap

Domanda: Spiega il sistema di griglia di Bootstrap e come creare un layout a 3 colonne responsive.

Risposta: Bootstrap usa un sistema a 12 colonne con container, row e col. Per 3 colonne responsive:

<div class="container">
  <div class="row">
    <div class="col-md-4">Colonna 1</div>
    <div class="col-md-4">Colonna 2</div>
    <div class="col-md-4">Colonna 3</div>
  </div>
</div>

Su desktop saranno 3 colonne, su mobile si impilano verticalmente.

5. JavaScript

Domanda: Qual è la differenza tra let, const e var nella dichiarazione delle variabili?

Risposta: var ha function scope e può essere ridichiarata; let ha block scope e può essere riassegnata ma non ridichiarata; const ha block scope e non può essere né riassegnata né ridichiarata (per oggetti e array il contenuto può essere modificato ma non il riferimento).

6. JavaScript (DOM)

Domanda: Come selezionare un elemento HTML tramite JavaScript e aggiungere un event listener?

Risposta:

// Selezione per ID
const button = document.getElementById('mio-button');
// Aggiunta event listener
button.addEventListener('click', function() {
  console.log('Button cliccato!');
});

Caso 2

1. Programmazione/Sviluppo Web (Teorico)

Domanda: Cosa significa "progressive enhancement" nello sviluppo web e perché è importante?

Risposta: Progressive enhancement significa partire da una base HTML funzionante per tutti, poi aggiungere CSS per il design e JavaScript per l'interattività. È importante perché garantisce accessibilità, funzionalità anche con JavaScript disabilitato, migliori performance e compatibilità con tutti i browser e dispositivi.

2. HTML

Domanda: Spiega l'importanza dell'attributo alt nelle immagini e quando utilizzare il tag <figure>.

Risposta: L'attributo alt fornisce una descrizione testuale dell'immagine per screen reader e quando l'immagine non si carica, migliorando accessibilità e SEO. Il tag <figure> si usa per contenuti auto-contenuti (immagini, grafici, code) spesso con <figcaption> per la didascalia.

3. CSS

Domanda: Spiega il concetto di specificità in CSS e come viene calcolata.

Risposta: La specificità determina quale regola CSS viene applicata quando ci sono conflitti. Si calcola: inline styles (1000), IDs (100), classi/attributi/pseudo-classi (10), elementi/pseudo-elementi (1). Esempio: #header .nav a ha specificità 111 (1 ID + 1 classe + 1 elemento).

4. Bootstrap

Domanda: Qual è la differenza tra classi utility e componenti in Bootstrap? Fai esempi.

Risposta: Le classi utility sono singole proprietà CSS riutilizzabili (text-center, mb-3, d-flex). I componenti sono elementi UI completi predefiniti (navbar, card, modal). Le utility offrono flessibilità granulare, i componenti forniscono soluzioni complete e coerenti.

5. JavaScript

Domanda: Spiega la differenza tra == e === con esempi pratici.

Risposta: == confronta i valori con conversione di tipo automatica, === confronta valore e tipo senza conversioni. Esempi:

5 == "5"  // true (conversione automatica)
5 === "5" // false (tipi diversi)
0 == false // true
0 === false // false

6. CSS (Flexbox)

Domanda: Come utilizzare Flexbox per centrare un elemento sia orizzontalmente che verticalmente?

Risposta:

.container {
  display: flex;
  justify-content: center; /* centra orizzontalmente */
  align-items: center; /* centra verticalmente */
  height: 100vh; /* altezza necessaria */
}

Caso 3

1. Programmazione/Sviluppo Web (Teorico)

Domanda: Cosa sono le API REST e perché sono importanti nello sviluppo web moderno?

Risposta: Le API REST sono interfacce che permettono comunicazione tra applicazioni usando HTTP con metodi standard (GET, POST, PUT, DELETE). Sono importanti perché separano frontend e backend, permettono riutilizzo dei servizi, facilitano integrazione tra sistemi diversi e supportano architetture scalabili.

2. HTML

Domanda: Qual è la struttura base di un documento HTML5 e cosa fa il DOCTYPE?

Risposta:

<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Titolo</title>
</head>
<body>
  <!-- contenuto -->
</body>
</html>

Il DOCTYPE dice al browser di usare HTML5 e la modalità standard.

3. CSS

Domanda: Spiega la differenza tra display: none, visibility: hidden e opacity: 0.

Risposta: display: none rimuove completamente l'elemento dal layout; visibility: hidden nasconde l'elemento ma occupa ancora spazio; opacity: 0 rende l'elemento trasparente ma rimane interattivo e occupa spazio. Solo display: none non influenza il layout.

4. Bootstrap

Domanda: Quando è appropriato usare Bootstrap in un progetto e quando invece è meglio evitarlo?

Risposta: Bootstrap è utile per: prototipazione rapida, progetti con budget/tempo limitato, team con competenze CSS variabili, consistenza nel design. Da evitare quando: serve design molto personalizzato, performance critiche, progetti semplici, quando si vuole pieno controllo del CSS.

5. JavaScript

Domanda: Cosa sono le arrow functions e in cosa differiscono dalle funzioni tradizionali?

Risposta: Le arrow functions sono una sintassi più concisa: const sum = (a, b) => a + b. Differenze principali: non hanno proprio this (lo ereditano dal contesto), non possono essere usate come costruttori, non hanno arguments object, sintassi più breve per funzioni semplici.

6. JavaScript (Async)

Domanda: Cosa significa che JavaScript è single-threaded e come gestisce le operazioni asincrone?

Risposta: JavaScript esegue un'operazione alla volta nel main thread. Le operazioni asincrone (fetch, setTimeout) vengono delegate al browser/Node.js che le gestisce in background. Quando completate, i callback vengono messi nella queue e eseguiti dall'event loop quando il main thread è libero.

Approffondimenti cicli for/forEach/map/filter/find/reduce/flatMap

1. Cicli for vs forEach

Domanda: Qual è la differenza principale tra un ciclo for tradizionale e il metodo forEach? In quali situazioni preferiresti uno sull'altro?

Risposta: Il ciclo for ha controllo completo (break, continue, return), mentre forEach è più dichiarativo ma non può essere interrotto. Usa for quando hai bisogno di uscire anticipatamente o modificare l'indice, forEach per iterazioni semplici senza interruzioni.

// for - può uscire
for(let i = 0; i < array.length; i++) {
  if(array[i] === target) break; // OK
}

// forEach - non può uscire
array.forEach(item => {
  // break; NON funziona
});

2. map() - Concetto e return

Domanda: Analizza questo codice e spiega cosa restituisce map(). Cosa succede se non uso return in alcuni casi?

const numbers = [1, 2, 3, 4, 5];
const result = numbers.map(num => {
  if(num % 2 === 0) {
    return num * 2;
  }
  // Cosa succede qui per i numeri dispari?
});
console.log(result);

Risposta: map() restituisce sempre un nuovo array della stessa lunghezza dell'originale. Se non c'è return, l'elemento diventa undefined. Il risultato sarà [undefined, 4, undefined, 8, undefined]. Per i numeri dispari manca il return, quindi diventano undefined.

3. filter() - Logica di filtraggio

Domanda: Scrivi il codice per filtrare da un array di studenti solo quelli con voto >= 6, poi spiega cosa restituisce filter() se nessun elemento soddisfa la condizione.

Risposta:

const studenti = [
  {nome: "Marco", voto: 7},
  {nome: "Anna", voto: 5},
  {nome: "Luigi", voto: 8}
];

const promossi = studenti.filter(studente => studente.voto >= 6);
// Risultato: [{nome: "Marco", voto: 7}, {nome: "Luigi", voto: 8}]

Se nessun elemento soddisfa la condizione, filter() restituisce un array vuoto [], mai null o undefined.

4. Differenze tra forEach, map e filter

Domanda: Completa questa tabella spiegando le differenze:

Metodo Restituisce Modifica array originale Uso principale
forEach ? ? ?
map ? ? ?
filter ? ? ?

Risposta:

Metodo Restituisce Modifica array originale Uso principale
forEach undefined No (ma può modificare oggetti contenuti) Eseguire azioni su ogni elemento
map Nuovo array (stessa lunghezza) No Trasformare ogni elemento
filter Nuovo array (lunghezza <= originale) No Selezionare elementi che soddisfano condizione

5. Combinazione di metodi (Chaining)

Domanda: Dato un array di numeri, scrivi il codice per: filtrare solo i pari, moltiplicarli per 3, e sommarli. Spiega l'ordine delle operazioni.

Risposta:

const numbers = [1, 2, 3, 4, 5, 6, 8, 10];

const risultato = numbers
  .filter(num => num % 2 === 0)    // [2, 4, 6, 8, 10]
  .map(num => num * 3)             // [6, 12, 18, 24, 30]  
  .reduce((sum, num) => sum + num, 0); // 90

console.log(risultato); // 90

L'ordine è importante: prima filtra (reduce l'array), poi trasforma (map), infine aggrega (reduce).

6. Performance e casi d'uso

Domanda: Hai un array di 10.000 elementi e devi trovare il primo elemento che soddisfa una condizione. Quale approccio sceglieresti tra for, forEach, find() e perché?

Risposta: Userei find() o un ciclo for con break.

// MIGLIORE - si ferma al primo match
const result = array.find(item => item.condition);

// O ciclo for con break
for(let i = 0; i < array.length; i++) {
  if(array[i].condition) {
    result = array[i];
    break; // IMPORTANTE: esce subito
  }
}

// PESSIMO - controlla tutto l'array anche dopo aver trovato
array.forEach(item => { /* non può fermarsi */ });

forEach continuerebbe a controllare tutti i 10.000 elementi anche dopo aver trovato il primo.

7. Immutabilità e side effects

Domanda: Analizza questi due approcci per incrementare tutti i numeri in un array. Quale è preferibile e perché?

// Approccio A
const numbers = [1, 2, 3];
for(let i = 0; i < numbers.length; i++) {
  numbers[i]++;
}

// Approccio B  
const numbers = [1, 2, 3];
const incremented = numbers.map(num => num + 1);

Risposta: L'Approccio B è preferibile perché:

  • Immutabilità: non modifica l'array originale
  • Predicibilità: numbers rimane invariato, incremented è il nuovo array
  • Functional programming: più facile da testare e debuggare
  • Evita side effects: non ci sono modifiche inaspettate ad altri punti del codice che usano numbers
// Approccio A: numbers diventa [2, 3, 4] (MODIFICATO)
// Approccio B: numbers rimane [1, 2, 3], incremented è [2, 3, 4]

8. map() per filtrare l'Array

Domanda: Posso con solo uso di map() fare in modo di avere un nuovo array che contenga solo i valori desiderati?

Risposta: Con map() non puoi davvero "non restituire niente" perché mantiene sempre la stessa lunghezza dell'array originale. Ecco pero' le opzioni:

Opzioni con map()

1. Restituire undefined (ma rimane nell'array)

const numbers = [1, 2, 3, 4, 5];

const result = numbers.map(num => {
  if(num % 2 === 0) {
    return num * 2;
  }
  // Non restituisce nulla = undefined
});

console.log(result); // [undefined, 4, undefined, 8, undefined]

2. Usare flatMap() per "saltare" elementi

const numbers = [1, 2, 3, 4, 5];

const result = numbers.flatMap(num => {
  if(num % 2 === 0) {
    return [num * 2]; // Array con un elemento
  }
  return []; // Array vuoto = niente nell'output finale
});

console.log(result); // [4, 8] - gli array vuoti spariscono!

Soluzioni migliori

3. Combinare filter() + map()

const numbers = [1, 2, 3, 4, 5];

const result = numbers
  .filter(num => num % 2 === 0)  // Solo pari: [2, 4]
  .map(num => num * 2);          // Trasforma: [4, 8]

console.log(result); // [4, 8]

4. Usare reduce() per controllo completo

const numbers = [1, 2, 3, 4, 5];

const result = numbers.reduce((acc, num) => {
  if(num % 2 === 0) {
    acc.push(num * 2);
  }
  // Se non è pari, non aggiungo nulla
  return acc;
}, []);

console.log(result); // [4, 8]

Esempio pratico di domanda per studenti:

Domanda: "Hai un array di studenti e vuoi ottenere solo i nomi di quelli promossi (voto >= 6), trasformati in maiuscolo. Confronta questi tre approcci:"

const studenti = [
  {nome: "marco", voto: 7},
  {nome: "anna", voto: 4}, 
  {nome: "luigi", voto: 8},
  {nome: "sara", voto: 5}
];

// Approccio 1: map (SBAGLIATO)
const result1 = studenti.map(s => {
  if(s.voto >= 6) return s.nome.toUpperCase();
  // undefined per i bocciati
});
// Risultato: ["MARCO", undefined, "LUIGI", undefined]

// Approccio 2: filter + map (CORRETTO)
const result2 = studenti
  .filter(s => s.voto >= 6)
  .map(s => s.nome.toUpperCase());
// Risultato: ["MARCO", "LUIGI"]

// Approccio 3: flatMap (ALTERNATIVA)
const result3 = studenti.flatMap(s => {
  if(s.voto >= 6) return [s.nome.toUpperCase()];
  return [];
});
// Risultato: ["MARCO", "LUIGI"]

La regola d'oro: Se vuoi un array più piccolo dell'originale, usa filter() poi map(), non solo map()!


Approfondimento Javascript single-threaded e Async

Questo è uno dei concetti più importanti e spesso fraintesi di JavaScript. Approfondiamo tutto:

1. Cosa significa "Single-Threaded"?

JavaScript ha un solo thread principale (main thread) che esegue il codice. Significa che può fare una sola cosa alla volta:

console.log("1");
console.log("2"); 
console.log("3");
// Eseguite in sequenza, una dopo l'altra

Ma allora come fa a gestire operazioni che richiedono tempo (API, timer, file)?

2. L'Event Loop e le Web APIs

Il browser (o Node.js) fornisce Web APIs che girano in background:

console.log("Inizio"); // 1° - Sincrono

setTimeout(() => {
    console.log("Timer finito"); // 4° - Asincrono
}, 2000);

fetch('https://api.github.com/users/octocat')
    .then(response => response.json())
    .then(data => console.log(data)); // 5° - Asincrono

console.log("Fine"); // 2° - Sincrono

// Output:
// "Inizio"
// "Fine"  
// (dopo 2 secondi) "Timer finito"
// (quando arriva risposta) {...dati utente...}

3. Come funziona internamente

CALL STACKWEB APIsCALLBACK QUEUEEVENT LOOP

// Esempio pratico
console.log("1 - Sincrono"); 

setTimeout(() => {
    console.log("3 - Da timer");
}, 0); // Anche con 0ms!

Promise.resolve().then(() => {
    console.log("2 - Da Promise");
});

console.log("4 - Sincrono");

// Output: 1, 4, 2, 3
// Le Promise hanno priorità sui timer!

Perché questo ordine?

  • console.log va direttamente nel Call Stack
  • setTimeout va nelle Web APIs, poi nella Macro Queue
  • Promise va nella Micro Queue (priorità maggiore)
  • Event Loop controlla prima Micro Queue, poi Macro Queue

4. Richieste API con Callback (metodo vecchio)

// CALLBACK HELL - Da evitare!
function getUserData(userId, callback) {
    // Simula chiamata API
    setTimeout(() => {
        const user = { id: userId, name: "Marco" };
        callback(null, user);
    }, 1000);
}

function getUserPosts(userId, callback) {
    setTimeout(() => {
        const posts = ["Post 1", "Post 2"];
        callback(null, posts);
    }, 1000);
}

// Uso - diventa un disastro!
getUserData(1, (err, user) => {
    if(err) return console.error(err);
    
    getUserPosts(user.id, (err, posts) => {
        if(err) return console.error(err);
        
        console.log(user, posts);
        // E se dovessi fare un'altra chiamata?
        // Altri callback annidati...
    });
});

5. Promise - La soluzione moderna

// Stessa logica con Promise
function getUserData(userId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if(userId <= 0) {
                reject(new Error("ID non valido"));
            } else {
                resolve({ id: userId, name: "Marco" });
            }
        }, 1000);
    });
}

function getUserPosts(userId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(["Post 1", "Post 2"]);
        }, 1000);
    });
}

// Uso con .then() - Molto più pulito!
getUserData(1)
    .then(user => {
        console.log("User:", user);
        return getUserPosts(user.id);
    })
    .then(posts => {
        console.log("Posts:", posts);
    })
    .catch(error => {
        console.error("Errore:", error);
    });

6. Fetch API - Richieste HTTP reali

// GET Request
fetch('https://jsonplaceholder.typicode.com/users/1')
    .then(response => {
        if(!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
    })
    .then(user => {
        console.log(user);
        document.getElementById('user-name').textContent = user.name;
    })
    .catch(error => {
        console.error('Errore fetch:', error);
    });

// POST Request
const newUser = {
    name: 'Marco Rossi',
    email: '[email protected]'
};

fetch('https://jsonplaceholder.typicode.com/users', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(newUser)
})
.then(response => response.json())
.then(data => console.log('Utente creato:', data))
.catch(error => console.error('Errore:', error));

7. Async/Await - Sintassi moderna

// Stesso codice ma più leggibile
async function fetchUserAndPosts(userId) {
    try {
        // Le operazioni sembrano sincrone ma sono asincrone!
        const user = await getUserData(userId);
        console.log("User:", user);
        
        const posts = await getUserPosts(user.id);
        console.log("Posts:", posts);
        
        return { user, posts };
    } catch (error) {
        console.error("Errore:", error);
        throw error; // Re-throw per chi chiama la funzione
    }
}

// Uso
fetchUserAndPosts(1)
    .then(result => {
        console.log("Risultato completo:", result);
    });

// O dentro un'altra async function
async function main() {
    const result = await fetchUserAndPosts(1);
    console.log("Risultato:", result);
}

8. Operazioni in parallelo vs sequenza

// SEQUENZIALE - Una dopo l'altra (più lento)
async function sequential() {
    console.time("Sequential");
    
    const user1 = await fetch('/api/users/1').then(r => r.json());
    const user2 = await fetch('/api/users/2').then(r => r.json());
    const user3 = await fetch('/api/users/3').then(r => r.json());
    
    console.timeEnd("Sequential"); // ~3 secondi
    return [user1, user2, user3];
}

// PARALLELO - Tutte insieme (più veloce)
async function parallel() {
    console.time("Parallel");
    
    const [user1, user2, user3] = await Promise.all([
        fetch('/api/users/1').then(r => r.json()),
        fetch('/api/users/2').then(r => r.json()),
        fetch('/api/users/3').then(r => r.json())
    ]);
    
    console.timeEnd("Parallel"); // ~1 secondo
    return [user1, user2, user3];
}

9. Gestione errori avanzata

async function robustApiCall() {
    const maxRetries = 3;
    let attempt = 0;
    
    while(attempt < maxRetries) {
        try {
            const response = await fetch('/api/data');
            
            if(!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            return await response.json();
            
        } catch (error) {
            attempt++;
            console.log(`Tentativo ${attempt} fallito:`, error.message);
            
            if(attempt >= maxRetries) {
                throw new Error(`Falliti tutti i ${maxRetries} tentativi`);
            }
            
            // Aspetta prima di riprovare (exponential backoff)
            await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
        }
    }
}

10. Domande per testare la comprensione

Domanda A: Cosa stampa questo codice e in che ordine?

console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

Risposta: 1, 4, 3, 2 (Promise ha priorità su setTimeout)

Domanda B: Come faresti questa chiamata in parallelo invece che in sequenza?

// Da migliorare
async function getData() {
    const users = await fetch('/api/users').then(r => r.json());
    const products = await fetch('/api/products').then(r => r.json());
    return { users, products };
}

Risposta:

async function getData() {
    const [users, products] = await Promise.all([
        fetch('/api/users').then(r => r.json()),
        fetch('/api/products').then(r => r.json())
    ]);
    return { users, products };
}

Il punto chiave: JavaScript è single-threaded ma non bloccante grazie all'Event Loop e alle Web APIs che gestiscono le operazioni asincrone in background!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment