5 compiti tipici nei colloqui di lavoro su JavaScript: analisi e soluzioni

5 compiti tipici nei colloqui di lavoro su JavaScript: analisi e soluzioni

Dall'autore: abbiamo pubblicato per voi un articolo di Maria Antonietta Perna, che parla delle tipiche domande di JavaScript, comunemente proposte ai candidati programmatori durante i colloqui. L'articolo sarà utile principalmente per i programmatori alle prime armi.

I colloqui nelle aziende tecnologiche sono da tempo diventati un argomento di discussione. Non c'è da meravigliarsi, poiché superare un colloquio con successo offre l'opportunità di ottenere un buon lavoro. Ma non è così semplice, dato che spesso è necessario risolvere compiti complessi.

In effetti, la maggior parte di questi compiti non ha relazione con il lavoro che svolgerà il candidato, ma devono comunque essere risolti. A volte è necessario esibirli su una lavagna, senza consultare Google o qualsiasi altra fonte. Sì, la situazione sta lentamente cambiando, e in alcune aziende si rinuncia a tali colloqui, ma molti datori di lavoro seguono ancora questa tradizione. Questo articolo è dedicato all'analisi delle tipiche domande JavaScript che vengono spesso utilizzate come compiti per i candidati.

Ricordiamo: per tutti i lettori di «Habr» — sconto di 10.000 rubli per l'iscrizione a qualsiasi corso Skillbox con il codice promozionale «Habr».

Skillbox consiglia: Corso pratico «Sviluppatore mobile PRO».

La cosa principale è prepararsi con cura per il colloquio

Sì, prima di iniziare a discutere le mansioni, diamo un'occhiata ai consigli generali per prepararsi al colloquio.

La cosa più importante è prepararsi in anticipo. Verifica quanto bene ricordi gli algoritmi e le strutture dati e aggiorna le tue conoscenze nelle aree in cui non sei troppo sicuro. Ci sono diverse piattaforme online che possono aiutarti a prepararti per i colloqui. Ti consigliamo di GeeksforGeeks, Pramp, Interviewing.io e CodeSignal.

È utile imparare a esprimere le soluzioni ad alta voce. È consigliabile spiegare ai candidati cosa stai facendo, invece di scrivere semplicemente sulla lavagna (o digitare il codice al computer, in silenzio). In questo modo, se commetti un errore nel codice, ma il ragionamento è fondamentalmente corretto, puoi aumentare le tue possibilità di successo.

Devi riflettere sulla mansione prima di iniziare a risolverla. In alcuni casi, potresti comprendere superficialmente il compito e poi prendere un percorso errato. Potrebbe valere la pena porre alcune domande di chiarimento all'intervistatore.

È necessario esercitarsi a scrivere codice a mano, e non al PC. Capita che durante i colloqui ai candidati venga dato un marcatore e una lavagna, senza alcun suggerimento o formattazione automatica. Quando si cerca una soluzione, è utile annotare il codice su un foglio di carta o direttamente sulla lavagna. Se si tiene tutto a mente, si può dimenticare qualcosa di importante.

Esercizi standard su JavaScript

Probabilmente alcune di queste sfide ti sono già familiari. Può darsi che tu abbia già partecipato a colloqui in cui era necessario risolvere qualcosa di simile, oppure che tu stia praticando durante il tuo percorso di apprendimento di JavaScript. Ora è giunto il momento di risolverli di nuovo, con una spiegazione dettagliata del processo.

Palindromo

Un palindromo è una parola, una frase o una sequenza di caratteri che si legge esattamente allo stesso modo sia da sinistra a destra che da destra a sinistra. Ad esempio, 'Anna' è un palindromo, mentre 'table' e 'John' non lo sono.

Problema

Data una stringa; è necessario scrivere una funzione che restituisca il valore true se la stringa è un palindromo e false se non lo è. È importante considerare spazi e punteggiatura.

palindrome('racecar') === true
palindrome('table') === false

Analizziamo il compito

L'idea principale qui è invertire la stringa. Se la stringa "invertita" è completamente identica all'originale, significa che abbiamo ottenuto un palindromo e la funzione deve restituire true. Altrimenti, false.

Soluzione

Ecco il codice che permette di risolvere il palindromo.

const palindrome = str => {
  // trasforma la stringa in minuscolo
  str = str.toLowerCase()
  // inverte la stringa di input e restituisce il risultato del
  // confronto
  return str === str.split('').reverse().join('')
}

Il primo passo è convertire i caratteri della stringa di input in minuscolo. Questa è una garanzia che il programma confronterà proprio i caratteri, non il loro formato o altro.

Il secondo passo è invertire la stringa. Non è difficile: bisogna trasformarla in un array usando il metodo .split() (libreria String). Poi invertiamo l'array, utilizzando .reverse() (libreria Array). L'ultimo passaggio è convertire l'array invertito in una stringa con .join() (libreria Array).

Ora tutto ciò che resta da fare è confrontare la stringa "invertita" con l'originale, restituendo true o false.

FizzBuzz

Uno dei problemi più popolari nelle interviste.

Problema

È necessario scrivere una funzione che stampi sulla console i numeri da 1 a n, dove n è un numero intero fornito come parametro alla funzione, con le seguenti condizioni:

  • stampa fizz al posto dei numeri multipli di 3;
  • stampa buzz al posto dei numeri multipli di 5;
  • stampa fizzbuzz al posto dei numeri multipli sia di 3 che di 5.

Esempio

Fizzbuzz(5)

Risultato

// 1
// 2
// fizz
// 4
// buzz

Analizziamo il compito

La cosa principale qui è il metodo per trovare i multipli usando JavaScript. Può essere implementato utilizzando l'operatore modulo o resto — %, che mostra il resto della divisione di due numeri. Se il resto è 0, significa che il primo numero è multiplo del secondo.

12 % 5 // 2 -> 12 non è un multiplo di 5
12 % 3 // 0 -> 12 è un multiplo di 3

Quindi, se dividiamo 12 per 5, otteniamo 2 con un resto di 2. Se dividiamo 12 per 3, otteniamo 4 con un resto di 0. Nel primo caso 12 non è multiplo di 5, nel secondo — 12 è multiplo di 3.

Soluzione

La soluzione ottimale sarà il seguente codice:

const fizzBuzz = num => {
  for(let i = 1; i <= num; i++) {
    // controlla se il numero è un multiplo di 3 e 5
    if(i % 3 === 0 && i % 5 === 0) {
      console.log('fizzbuzz')
    } // controlla se il numero è un multiplo di 3
      else if(i % 3 === 0) {
      console.log('fizz')
    } // controlla se il numero è un multiplo di 5
      else if(i % 5 === 0) {
      console.log('buzz')
    } else {
      console.log(i)
    }
  }
}

La funzione esegue i controlli necessari utilizzando operatori condizionali e fornisce il risultato richiesto all'utente. È importante prestare attenzione all'ordine degli operatori if…else: si inizia con la condizione doppia (&&) e si termina con il caso in cui non si trovano numeri multipli. In questo modo copriamo tutte le opzioni.

Anagramma

Si tratta di una parola che contiene tutte le lettere di un'altra parola nello stesso numero, ma in ordine diverso.

Problema

È necessario scrivere una funzione che verifichi se due stringhe sono anagrammi, considerando che il caso delle lettere non influisce. Sono da considerare solo i caratteri; spazi o punteggiatura non vengono presi in considerazione.

anagram(‘finder’, ‘Friend’) —> true
anagram(‘hello’, ‘bye’) —> false

Analizziamo il compito

È importante tenere a mente che è necessario controllare ogni lettera delle due stringhe di input e il loro conteggio in ciascuna stringa.

finder —> f: 1 friend —> f: 1
i: 1 r: 1
n: 1 i: 1
d: 1 e: 1
e: 1 n: 1
r: 1 d: 1

Per memorizzare i dati degli anagrammi, è consigliabile utilizzare una struttura come un oggetto letterale JavaScript. In questo caso, la chiave sarà il carattere della lettera e il valore sarà il numero delle sue ripetizioni nella stringa attuale.

Ci sono anche altre condizioni:

  • È necessario assicurarsi che il confronto non tenga conto del maiuscolo o minuscolo. Convertiamo semplicemente entrambe le stringhe in minuscolo o maiuscolo.
  • Escludiamo dal confronto tutti i non simboli. È meglio lavorare con espressioni regolari.

Soluzione

// helper function that builds the
// object to store the data
const buildCharObject = str => {
  const charObj = {}
  for(let char of str.replace(/[^w]/g).toLowerCase()) {
    // if the object has already a key value pair
    // equal to the value being looped over,
    // increase the value by 1, otherwise add
    // the letter being looped over as key and 1 as its value
    charObj[char] = charObj[char] + 1 || 1
  }
  return charObj
}
 
// main function
const anagram = (strA, strB) => {
  // build the object that holds strA data
  const aCharObject = buildCharObject(strA)
  // build the object that holds strB data
  const bCharObject = buildCharObject(strB)
 
  // compare number of keys in the two objects
  // (anagrams must have the same number of letters)
  if(Object.keys(aCharObject).length !== Object.keys(bCharObject).length) {
    return false
  }
  // if both objects have the same number of keys
  // we can be sure that at least both strings
  // have the same number of characters
  // now we can compare the two objects to see if both
  // have the same letters in the same amount
  for(let char in aCharObject) {
    if(aCharObject[char] !== bCharObject[char]) {
      return false
    }
  }
  // if both the above checks succeed,
  // you have an anagram: return true
  return true
}

Si prega di notare l'uso di Object.keys() nel frammento sopra. Questo metodo restituisce un array contenente i nomi o le chiavi nello stesso ordine in cui si trovano nell'oggetto. In questo caso, l'array sarà il seguente:

['f', 'i', 'n', 'd', 'e', 'r']

In questo modo otteniamo le proprietà dell'oggetto senza la necessità di eseguire un ciclo pesante. In questo caso, si può utilizzare questo metodo con la proprietà .length per controllare se entrambe le stringhe contengono lo stesso numero di caratteri: è una caratteristica importante delle anagrammi.

Ricerca delle vocali

Un compito piuttosto semplice, che si incontra spesso durante i colloqui.

Problema

È necessario scrivere una funzione che prenda una stringa come argomento e restituisca il numero di vocali contenute nella stringa.
Le vocali sono "a", "e", "i", "o", "u".

Esempio:

findVowels('hello') // -> 2
findVowels('why') // -> 0

Soluzione

Ecco la soluzione più semplice:

const findVowels = str => {
  let count = 0
  const vowels = ['a', 'e', 'i', 'o', 'u']
  for(let char of str.toLowerCase()) {
    if(vowels.includes(char)) {
      count++
    }
  }
  return count
}

È importante prestare attenzione all'uso del metodo .includes(). È disponibile sia per le stringhe che per gli array. È utile per determinare se un array contiene un determinato valore. Questo metodo restituisce true se l'array contiene il valore specificato e false in caso contrario.

Esiste anche una soluzione più concisa al problema:

const findVowels = str => {
  const matched = str.match(/[aeiou]/gi)
  return matched ? matches.length : 0
}

Qui viene utilizzato il metodo .match(), che permette di eseguire una ricerca efficace. Se l'espressione regolare come argomento del metodo viene trovata nella stringa specificata, il valore restituito è un array di caratteri corrispondenti. Se non ci sono corrispondenze, .match() restituisce null.

Fibonacci

Un problema classico che può essere incontrato in colloqui di lavoro di vari livelli. Vale la pena ricordare che la sequenza di Fibonacci è una serie di numeri in cui ogni numero successivo è la somma dei due precedenti. Così, i primi dieci numeri sono i seguenti: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.

Problema

Devi scrivere una funzione che restituisce il n-esimo valore in una specifica sequenza, dove n è il numero passato come argomento della funzione.

fibonacci(3) // -> 2

Questo compito comporta l'esecuzione di un ciclo per il numero di volte specificato nell'argomento, restituendo il valore alla posizione corrispondente. Questo tipo di formulazione richiede l'uso di cicli. Se invece utilizzi la ricorsione, potrebbe piacere all'intervistatore e darti qualche punto in più.

Soluzione

const fibonacci = num => {
  // memorizza la sequenza di Fibonacci che stai per
  // generare all'interno di un array e
  // inizializza l'array con i primi due
  // numeri della sequenza
  const result = [0, 1]

  for(let i = 2; i <= num; i++) {
    // aggiungi la somma dei due numeri
    // precedenti alla posizione di i nell'array dei risultati
    // alla fine dell'array dei risultati
    const prevNum1 = result[i - 1]
    const prevNum2 = result[i - 2]
    result.push(prevNum1 + prevNum2)
  }
  // restituisci l'ultimo valore nell'array dei risultati
  return result[num]
}

Nel array dei risultati, i primi due numeri sono presenti nella sequenza, poiché ogni valore nella serie è la somma dei due numeri precedenti. All'inizio non ci sono due numeri da cui partire per generare il successivo, quindi il ciclo non può generarli automaticamente. Ma, come sappiamo, i primi due numeri sono sempre 0 e 1. Pertanto, possiamo inizializzare manualmente l'array dei risultati.

Per quanto riguarda la ricorsione, qui le cose sono sia più semplici che più complesse:

const fibonacci = num => {
  // se num è 0 o 1, restituisci num
  if(num < 2) {
    return num
  }
  // ricorsione qui
  return fibonacci(num - 1) + fibonacci(num - 2)
}

Continuiamo a chiamare fibonacci(), passando numeri sempre più piccoli come argomenti. Ci fermiamo quando l'argomento passato è 0 o 1.

Risultato

Probabilmente hai già incontrato alcune delle sfide menzionate, se hai sostenuto colloqui per posizioni come frontend o sviluppatore JavaScript (specialmente a livello junior). Ma se non ti sono mai capitate, potrebbero tornarti utili in futuro, perlomeno per la tua crescita personale.

Skillbox consiglia:

Fonte: habr.com

Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista un hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster